Pushing UIViewController from SideMenu sometimes blinks/flashes
Closed this issue · 24 comments
Describe the bug
I use SideMenu to show a UITableView with 4 different options for the user to navigate to and another UITableViewCell to log out. This all works correctly, however, since iOS 13, when one of the 4 UIViewControllers is pushed, sometimes a short blink/flash appears right after the UIViewController was shown. I have tried to navigate in other ways outside of SideMenu, and this problem doesn't happen when pushing regularly, making me think the bug is associated with SideMenu.
To Reproduce
Steps to reproduce the behavior:
- I instantiate SideMenu as follows:
var sideMenuManager = SideMenuManager.init()
var sideMenuController = SideMenuController()
menuLeftNavigationController = SideMenuNavigationController(rootViewController: sideMenuController)
sideMenuManager.leftMenuNavigationController = menuLeftNavigationController
menuLeftNavigationController.menuWidth = max(round(sideMenuWidth), 240)
menuLeftNavigationController.dismissOnPush = true
menuLeftNavigationController.statusBarEndAlpha = 0
menuLeftNavigationController.presentationStyle = .viewSlideOutMenuIn
menuLeftNavigationController.presentationStyle.presentingEndAlpha = 0.5
sideMenuManager.addScreenEdgePanGesturesToPresent(toView: navView)
- To push a UIViewController, I use the following code inside my Side Menu ViewController (SideMenuController):
let pushVC = MyCustomViewController()
let navViewController = self.navigationController
navViewController?.pushViewController(pushVC, animated: true)
- When the UIViewController shows, most of the time it's OK, but in 1 out of every 5 cases or so, a short blink or flash appears on the screen for a couple of milliseconds.
Expected behavior
Before iOS 13, this was all working smoothly, without blinks/flashes. Was hoping I was able to go back to the smooth-running pushes.
Is this reproducible in the demo project? If so, please use that project as there may be other root causes in your own project causing this issue.
A little more info so far. I think there might be something I am doing wrong, but I feel confident it has something to do with the SideMenu project.
I noticed, using slow animations in debug mode, the flash occurs right before the push has completed (literally when the pushed viewController is almost completely visible).
Also, when I use my main view controller (the home screen of my app) as navigationController to push from, the flash doesn't occur. So, when I use:
let pushVC = MyCustomViewController()
let navViewController = HomeViewController.navigationController
navViewController?.pushViewController(pushVC, animated: true)
the flash does not occur. However, as this could be the solution, it doesn't call the dismissal function (dismissOnPush is set to true, which I want, but the SideMenu does not close when I push from the HomeViewController). I tried animating this myself, using self.dismiss(animated: true) but this doesn't animate properly alongside each other (the pushed VC is shown first, then the dismiss animation happens, so it doesn't occur in parallel).
I have been spending a couple of hours now on trying to find the issue and fixing it, but I don't seem to find it. As mentioned before, all my pushes work correctly throughout my app, only from the SideMenu the flash occurs.
I think it is because the navigationController of the SideMenu is pushing the ViewController I want to show, but then something happens in the hierarchy between the HomeViewController (which is still a little visible when the SideMenu is visible) and the presented ViewController. Any ideas?
I don't, unfortunately. Best I can think of is it's the last second removal of SideMenu and restoring your controllers back into the main window from the animation container. Again, I don't see this in any of my apps or in the demo project, which leads me to think there's something going on with your code and not SideMenu.
If you want, you can manually dismiss SideMenu and then push your view controller to not rely on SideMenu's dual animation, but it will take longer to finish the entire transition.
So I have looked into it deeper, recorded the screen and was able to pause it when the blink occurs. It blacks out the entire screen for a split second before showing the newly pushed UIViewController on screen.
First, I thought a new UINavigationController was initiated and everything was loaded in there, but when I print self.navigationController, the reference is the same everywhere - thus the UINavigationController is still the same before and after pushing.
I do a bit of visual work/customization on the UINavigationBar, but tried removing all visual elements like backgroundColors etc. and the flash still happens.
MOV file of the flash to illustrate the problem more clearly, which you can pause around frame 22 (right after the first second) to see the black flash: MOV file
No idea if it's caused by something in the SideMenu library or because of something I do in code, but it started happening after I upgraded to the newest version of SideMenu (6.x.x), before I was using 5.x.x.
I'll now look into if I can do the animation myself and if this fixes the problem.
Just downgraded to the 4.2 branch (pod 'SideMenu', '~> 5.0'), which still runs fine. Can confirm the bug does not appear when using this release. The blinking/flashing is gone. Makes me think it has something to do with the UINavigationController changes in the 6.0 branch. However, I will use this branch for now as it does everything I need and it doesn't contain bugs as far as I have now noticed.
You're certainly welcome to downgrade, however that's not recommended as it's no longer supported and at some point in the future you'll hit a wall.
I still don't have anything to go on to troubleshoot your problem on my end so there won't be any fixes made for this issue. I wish I could be more helpful but I simply don't know. All I know is that the demo project works as expected and you're the first person to mention this. That leads me to believe it's specific with your implementation (doing something atypical or using a conflicting 3rd party library) and how SideMenu is interacting with it.
SideMenuPresentationController.dismissalTransitionDidEnd
is called as the last part of the transition where the flash would most likely happen. Perhaps you're messing with layer zPositioning?
Also, your settings in the initial report of the bug don't cause any issues in the demo project when I test it on 13.0 and 12.2.
Not doing anything with zPositioning. However, I do have a UINavigationController and a UITabBarController. Could the culprit be in there? I have no idea what else could cause this. I'm not as experienced as you are, by far not, but I feel like it should be in the UINavigationController or UITabBarController as all other views are shown in there - hence I would be surprised if these would cause the entire screen (not only the view itself) to black out.
I've also tried putting the demo project in a tab bar... it works as expected.
@pennywise94 same issue occurred to me. Please update it here if you find any work around for latest release. Thanks
@mohanmoorthyk I haven’t so far. I fell back to the previous release which worked, and still works, for me. Do you have any more insights to reproduce the problem?
Another user provided a clearer explanation of the flash. It has to do with presenting modally, not pushing.
Update to 6.4.7
and see if this resolves your issue.
same problem, version 6.4.8
same here, any fix yet ?
I cannot fix a problem that I cannot reproduce. Please provide a modified version of the demo project demonstrating the issue.
Finallyyyyyyy 🎉🎉🎉 It works perfectly
I discovered that Side Menu Disappearing and
SideMenu Disappeared are called twice every time I pushViewController , no idea why , I tried everything but couldn't know why, and couldn't reproduce the same issue in the demo project.
So what I did is to set SideMneu Settings dismissOnPush = false
and then I dismiss the menu manually,
I used this navigation extension to gain benefit of having a complication handler on pushing controller so I can dismiss the menu in the handler
public extension UINavigationController { func pushViewController(_ viewController: UIViewController, animated: Bool = true, completion: (() -> Void)? = nil) { CATransaction.begin() CATransaction.setCompletionBlock(completion) pushViewController(viewController, animated: animated) CATransaction.commit() } }
make sure to set animated to false 😁, and every thing will work as accepted, smooth , no blink , Side Menu Disappearing and
SideMenu Disappeared are NOT called twice only once, tested on two of my projects having the same issue.
Now I can die peacefully 🤤
Is this reproducible in the demo project? If so, please use that project as there may be other root causes in your own project causing this issue.
reproducible on my project!
I can replicate this issue by calling a simple push from the presented menu controller.
navigationController?.pushViewController(vc, animated: false)
这个问题还没有解决,为什么就关闭了?
Having the same issue here :(
@abdulazizSi is it meant to be just enough to add your extension to the project? Or do I need to do more?
Because when i set SideMenuManager.default.leftMenuNavigationController?.dismissOnPush = false
the flashing stopped, but just adding your extension nothing happened.
Still facing this issue.
The same problem version 6.5.0
@pennywise94 @Kedar-27 @az-oolloow @northcity @i-tengfei @mohanmoorthyk
It works for me version 6.5.0
Add
extension UINavigationController { func pushViewController(_ viewController: UIViewController, animated: Bool = true, completion: (() -> Void)? = nil) { CATransaction.begin() CATransaction.setCompletionBlock(completion) viewController.view.backgroundColor = .white pushViewController(viewController, animated: animated) CATransaction.commit() } }
Set
SideMenuManager.default.leftMenuNavigationController?.dismissOnPush = false
In SideMenuManager I made public
public var activeMenu: Menu?
In SideMenuSettings I made public from internal
public typealias Menu = SideMenuNavigationController
When push
self.navigationController?.pushViewController(vc, animated: true, completion: {
SideMenuManager.default.activeMenu?.dismiss(animated: false)
})