Sidemenu: Crash when presenting UISideMenuNavigationController under specific circumstances

Created on 3 Dec 2016  路  38Comments  路  Source: jonkykong/SideMenu

I have detected a problem (well, not me, my users did) when presenting a UISideMenuNavigationController in a specific scenario.

This happens if I do the following steps:

  • Present the UISideMenuNavigationController (with a gesture or pressing a button... it's indifferent)
  • From this UISideMenuNavigationController, I present a view controller (e.g.: UIAlertViewController or MFMailComposeViewController)
  • While this view controller is showing, I press the home button
  • I go back to the app
  • At this moment, the UISideMenuNavigationController is hidden and looks like the view controller I presented is... dismissed?
  • Now, if I try to present the UISideMenuNavigationController again... crash!

And this is the crash log:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modally an active controller <App.SideMenuViewController: 0x1f12dba0>.'
*** First throw call stack:
(
    0   CoreFoundation                      0x09504212 __exceptionPreprocess + 194
    1   libobjc.A.dylib                     0x08ba8e66 objc_exception_throw + 52
    2   UIKit                               0x05456975 -[UIViewController _presentViewController:withAnimationController:completion:] + 5740
    3   UIKit                               0x05459b5a __62-[UIViewController presentViewController:animated:completion:]_block_invoke + 363
    4   UIKit                               0x05459ec3 -[UIViewController _performCoordinatedPresentOrDismiss:animated:] + 535
    5   UIKit                               0x054599a8 -[UIViewController presentViewController:animated:completion:] + 182
    6   SideMenu                            0x04f5017c _TZFC8SideMenu18SideMenuTransition20handlePresentMenuPanfCSo22UIPanGestureRecognizerT_ + 2284
    7   SideMenu                            0x04f4f74c _TZFC8SideMenu18SideMenuTransition31handlePresentMenuLeftScreenEdgefCSo32UIScreenEdgePanGestureRecognizerT_ + 76
    8   SideMenu                            0x04f4f7e7 _TToZFC8SideMenu18SideMenuTransition31handlePresentMenuLeftScreenEdgefCSo32UIScreenEdgePanGestureRecognizerT_ + 55
    9   UIKit                               0x058304c7 -[UIGestureRecognizerTarget _sendActionWithGestureRecognizer:] + 64
    10  UIKit                               0x05838eea _UIGestureRecognizerSendTargetActions + 109
    11  UIKit                               0x0583657a _UIGestureRecognizerSendActions + 288
    12  UIKit                               0x05835434 -[UIGestureRecognizer _updateGestureWithEvent:buttonEvent:] + 1059
    13  UIKit                               0x0581fe74 _UIGestureEnvironmentUpdate + 1461
    14  UIKit                               0x0581f877 -[UIGestureEnvironment _deliverEvent:toGestureRecognizers:usingBlock:] + 494
    15  UIKit                               0x0581ea21 -[UIGestureEnvironment _updateGesturesForEvent:window:] + 259
    16  UIKit                               0x052ee3b3 -[UIWindow sendEvent:] + 4276
    17  UIKit                               0x05294d88 -[UIApplication sendEvent:] + 395
    18  UIKit                               0x05b3c25d __dispatchPreprocessedEventFromEventQueue + 3706
    19  UIKit                               0x05b3433f __handleEventQueue + 5345
    20  CoreFoundation                      0x094a3cbf __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
    21  CoreFoundation                      0x09487df7 __CFRunLoopDoSources0 + 519
    22  CoreFoundation                      0x09487284 __CFRunLoopRun + 1124
    23  CoreFoundation                      0x09486bab CFRunLoopRunSpecific + 395
    24  CoreFoundation                      0x09486a0b CFRunLoopRunInMode + 123
    25  GraphicsServices                    0x0bb7fb4c GSEventRunModal + 177
    26  GraphicsServices                    0x0bb7f9c7 GSEventRun + 80
    27  UIKit                               0x0527432b UIApplicationMain + 148
    28  MyApp                               0x0011d3e1 main + 145
    29  libdyld.dylib                       0x0ac10799 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

Most helpful comment

I'm finding a crash after starting signed in (with side menu setup), then logging out, then signing in again. The side menu VC lingers in the view hierarchy in a UITransitionView, thus triggering the crash when trying to open after 2nd sign in. Will try a forced cleanup on signout - maybe this: https://stackoverflow.com/questions/26763020/leaking-views-when-changing-rootviewcontroller-inside-transitionwithview

All 38 comments

@waninkoko Verified this is occurring in the demo project as well. I have a fix prepared and will update it when I have a chance to incorporate outstanding pull requests.

That was fast, thanks!

By the way, could I get this patch so I can temporarely apply it into my project?

@jonkykong Oops, I just realized that I forgot to mention you, so you probably didn't get my previous message.

Change SideMenuTransition.swift:453 to:

        if let menuViewController: UINavigationController = SideMenuTransition.presentDirection == .left ? SideMenuManager.menuLeftNavigationController : SideMenuManager.menuRightNavigationController,
            menuViewController.presentedViewController == nil {

@jonkykong Thank you very much!

Fixed in 2.0.7.

I'm currently experiencing the same issue. It's not related to background the app in my case. Sometimes tapping on a UIBarButtonItem that shows a left menu crashes with the same exception.

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modally an active controller .'

* First throw call stack:
(
0 CoreFoundation 0x000000010541cd4b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x0000000104b1521e objc_exception_throw + 48
2 UIKit 0x0000000102f443f3 -[UIViewController _presentViewController:withAnimationController:completion:] + 5328
3 UIKit 0x0000000102f4726b -[UIViewController _performCoordinatedPresentOrDismiss:animated:] + 530
4 UIKit 0x0000000102f46d51 -[UIViewController presentViewController:animated:completion:] + 179
5 Anteo 0x0000000101ec2384 _TFC5Anteo17TabViewController14sideMenuTappedfT_T_ + 564
6 Anteo 0x0000000101ec25c2 _TToFC5Anteo17TabViewController14sideMenuTappedfT_T_ + 34
7 UIKit 0x0000000102d908bc -[UIApplication sendAction:to:from:forEvent:] + 83
8 UIKit 0x00000001031d24a1 -[UIBarButtonItem(UIInternal) _sendAction:withEvent:] + 149
9 UIKit 0x0000000102d908bc -[UIApplication sendAction:to:from:forEvent:] + 83
10 UIKit 0x0000000102f16c38 -[UIControl sendAction:to:forEvent:] + 67
11 UIKit 0x0000000102f16f51 -[UIControl _sendActionsForEvents:withEvent:] + 444
12 UIKit 0x0000000102f170db -[UIControl _sendActionsForEvents:withEvent:] + 838
13 UIKit 0x0000000102f15e4d -[UIControl touchesEnded:withEvent:] + 668
14 UIKit 0x0000000102dfe545 -[UIWindow _sendTouchesForEvent:] + 2747
15 UIKit 0x0000000102dffc33 -[UIWindow sendEvent:] + 4011
16 UIKit 0x0000000102dac9ab -[UIApplication sendEvent:] + 371
17 FLEX 0x000000010271a1c2 __35+[FLEXKeyboardShortcutManager load]_block_invoke.108 + 1026
18 UIKit 0x000000010359972d __dispatchPreprocessedEventFromEventQueue + 3248
19 UIKit 0x0000000103592463 __handleEventQueue + 4879
20 CoreFoundation 0x00000001053c1761 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
21 CoreFoundation 0x00000001053a698c __CFRunLoopDoSources0 + 556
22 CoreFoundation 0x00000001053a5e76 __CFRunLoopRun + 918
23 CoreFoundation 0x00000001053a5884 CFRunLoopRunSpecific + 420
24 GraphicsServices 0x000000010b648a6f GSEventRunModal + 161
25 UIKit 0x0000000102d8ec68 UIApplicationMain + 159
26 Anteo 0x0000000101e9699f main + 111
27 libdyld.dylib 0x000000010699368d start + 1
28 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

Would appreciate help!

@vardges you'll need to debug further. How are you investigating it? What have you tried? What does the error tell you?

Thanks for getting back to me, I thought that it was happening for every case, hence posted here. But I noticed it only happens when I setup my host view controller after login dynamically. If the host view controller is setup in app startup, the crash doesn't happen. Will debug further and report back if I find smth in the framework that's not working, but might be totally on my side.

I'm finding a crash after starting signed in (with side menu setup), then logging out, then signing in again. The side menu VC lingers in the view hierarchy in a UITransitionView, thus triggering the crash when trying to open after 2nd sign in. Will try a forced cleanup on signout - maybe this: https://stackoverflow.com/questions/26763020/leaking-views-when-changing-rootviewcontroller-inside-transitionwithview

@kkaliher It's difficult for me to comment on this problem without understanding the flow of your UI.

Generally speaking this should not be a SideMenu specific bug. If you present any view controller in your hierarchy, then present the same instance again, you'll get this exception. Even though SideMenu visually appears to dismiss when presenting a view controller from it, it does not. It simply hides itself so that when you return back to the prior screen, you're not left looking at an exposed menu which will often just be dismissed needlessly.

All of this is by design for fast transitioning to the presented view controller from the SideMenu, otherwise the user would have to wait for SideMenu to disappear and be removed from the hierarchy before a new screen can be presented. It is not possible to remove a view controller from the middle of the hierarchy when something is presented over it.

Your solutions are to re-think how you've structured your UI flow, create a new menu to be displayed instead of attempting to reuse the old one, or refactor the project to support multiple menu instances.

Right, it is not a SideMenu specific bug, no. I was able to work around it using the window extension provided at that SO link. More a feature request: a one-liner that cleans up SideMenu, including any 'stuck' or leaked UITransitionViews. This would be called by the app at some point after logout (and then SideMenu would need to be setup again freshly). I've seen a few related issue reports around this, and I suspect they are all coming from this particular flow.

@kkaliher The current design benefits the vast majority of developers as-is by enabling a one-time setup of SideMenu. Menus are kept in-memory so that they can be shown from multiple screens within the same level (ie. presenting creates a new level) without the need to set them up from every screen they're used on. This is deliberate and therefore not a leak.

I'm not clear on what the one-liner is that cleans up SideMenu.

Hi @jonkykong, I am also facing an issue of the same sort as above. I am pushing a view controller which edits my profile, with its navigation bar set to hidden = true. So when I implement the pan gesture which should show the side menu, the app crashes with the same error as above.

@midhetfatema94 You need to provide more information on the crash -- what was called, what line causes the exception, what is the exception. If you are in fact pushing as opposed to presenting, then I am not sure how you're facing a crash.

I ran into this issue when presenting modally on a SideMenuVC, putting the app in background, resuming, and then trying to present SideMenuVC again. The fix was to obviously not present on a SideMenuVC as it automatically dismisses itself anyway.

@kajensen I am unable to repro any issue using the demo project and latest code. Make sure you have the latest and can reproduce it; if so, please provide the clear repro steps/settings.

I can make you a demo project to reproduce it, but i'm not sure you necessarily need/want to fix it

@kajensen if the crash is occurring in the demo project, I would consider fixing it. Otherwise, if it is project specific and uncommonly hit, I would probably ignore it.

Hi
I ran into this issue when I sign in and logout then sign in again
the problem was that when user press the logout item I didn't dismiss the menu controller so when I am sign in again and try to present it it produce that error
so if any one face this issue please make sure first that you dismissed the sidemenucontroller first
thanks.

Same issue here when logging out and logging in. v3.1.5

For anyone still reporting this problem, please provide additional insight as to the repro steps, call stack, and problematic file/line in SideMenu.

I found two different solutions for the bug when logging out and logging in.

The correct one:
Dismiss the side view.

The easy one:
Do not use the default singleton. Instead create a new instance every time you need to instantiate a new view that uses the side view.

Indeed @jonkykong is correct and this is a fault in our code but the solution is not intuitive enough. Perhaps adding a more descriptive warning before crashing could help

@JuIioCesar any suggestions on what this warning might say?

When changing the side view:
[Warning] Side view was not dismissed and this could lead to a crash

Or even better we could support side view changes without dismissal.

@JuIioCesar any time a screen is presented from SideMenu, SideMenu remains in the view hierarchy. This is by design and the default behavior for all view controllers. Dismissing the menu first takes a moment of time and causes an unnecessary delay for the user.

From what I understand some developers are presenting a Sign In screen from the log out of SideMenu, and after the user signs in, instead of dismissing to return to the previous view hierarchy, they're instead presenting their starting app experience again, in essence having multiple instance of their app running which is a bad design. It's either that or they are trying to present SideMenu from the Sign In screen.

The supported solution is to create a new instance of SideMenu and not use the default one.

Unfortunately being able to change the menu after being presented will cause issues. The menu would be orphaned from the transition manager, making dismissal break or unpredicatble. Writing code to support all of that would likely introduce new bugs and I simply don't have the bandwidth to make them. You're welcome to investigate this yourself.

Another solution would be to always create new instance of each menu when needed, but I've noticed this causes brief delays when using gestures to present them, so they are instead held in memory per design.

I noticed that mostly this issue appears when login->logout operation is performed. The main issue is in our codes and most of us for logout case use segue to directly navigate into login screen but using unwind segue instead, will solve the issue.

@David-Grigoryan this is likely because you are re-presenting your app experience from logout while the signed-out experience is still in memory lower in the view hierarchy. This is bad for a number of reasons, including memory management.

@jonkykong Shouldn't the default open var menuDismissOnPush = true dismiss the menu when another view is pushed from it?

This is my use case:

LogoutButton clicked on side menu -> present login screen from side menu

I get the same issue as everyone on this thread, when trying to present the side menu again with the error: "Application tried to present modally an active controller", so is the menuDismissOnPush not doing what I think it is?

Edit: I also have a delegate watching the SideMenu and I can see the "SideMenu Disappeared!" text when the login screen is pushed.

@rapito Visually, it does. However due to the Apple behavior it is still in the view hierarchy until you return to the screen that displayed the SideMenu.

I was facing the same issue while implementing log in/Log out flow

i solved it by following technique.
First, when user taps logout, dismiss the menuLeftNavigationController.

SideMenuManager.default.menuLeftNavigationController!.dismiss(animated: true, completion: nil)

use a timer to allow for left menu to dismiss. i have set timer of 1 sec

Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { (timer) in

      //show your login view controllers
      let storyBoard = UIStoryboard.init(name: "Auth", bundle: nil)
      let nav = storyBoard.instantiateViewController(withIdentifier: "LoginNav")

      self.window?.rootViewController = nav
      self.window?.makeKeyAndVisible()

    }  

Upon logout call:

self.view.window!.rootViewController?.dismissViewControllerAnimated(false, completion: nil)

This will remove all active viewcontrollers and the crash message when trying to open the sidemenu will be gone... Took me a while to find this shit

hi @jonkykong .
I have same problem. I present or push a view controller from side menu. it present or push correctly . when I try to show side menu from presented view controller app crashes.
my presented view controller also must have access to present side menu . this is my error that I got in console:

2019-01-07 12:55:15.354915+0330 Al aan[1905:413570] - changing property cornerRadius in transform-only layer, will have no effect
SideMenu Warning: menuAddScreenEdgePanGesturesToPresent was called before menuLeftNavigationController was set. The gesture will not work without a menu. Use menuAddScreenEdgePanGesturesToPresent(toView:forMenu:) to add gestures for only one menu.
didSelectRow:[0, 3]
SideMenu Warning: menuRightNavigationController cannot be modified while it's presented.
SideMenu Warning: menuAddScreenEdgePanGesturesToPresent was called before menuLeftNavigationController was set. The gesture will not work without a menu. Use menuAddScreenEdgePanGesturesToPresent(toView:forMenu:) to add gestures for only one menu.
2019-01-07 12:56:24.835831+0330 Al aan[1905:413570] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modally an active controller .'
*
First throw call stack:
(0x1c9e53ea0 0x1c9025a40 0x1f69243a0 0x1f6926a38 0x1f692709c 0x1f6926990 0x1f6926ccc 0x101060c44 0x101016a60 0x101016ab4 0x1f6eda768 0x1f66aa6ec 0x1f66aa61c 0x1f6eda768 0x1f69686d0 0x1f69689f0 0x1f69679f0 0x1f6aed458 0x1f6ae8154 0x1c9de37a8 0x1c9dde43c 0x1c9dde9dc 0x1c9dde1cc 0x1cc055584 0x1f6ed9054 0x101032350 0x1c989ebb4)
libc++abi.dylib: terminating with uncaught exception of type NSException
warning: failed to set breakpoint site at 0x1015094ec for breakpoint 1.1: error sending the breakpoint request

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modally an active controller .'

I am facing the same issue when i logged in for the first time and clicked the side menu button. Is there any solution to resolve this issue.

@PanneerK @MohsenMoghimi does doing this solves your issues?

why do you just close the gihub project and make me not find this library and spend the whole time to fix this issue?

I am also getting this crash frequently.

Experiencing this crash right now on production and it's affecting majority of my users. Any solution?

Crashing at SideMenuPresentationController.swift, line 67

Was this page helpful?
0 / 5 - 0 ratings