iOS App Freezes on PushViewController

Great answer by @Penkey Suresh! Saved my day! Here's a SWIFT 3 version with a small addition that made the difference for me:

    func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {


    if (navigationController.viewControllers.count > 1)
    {
         self.navigationController?.interactivePopGestureRecognizer?.delegate = self
        navigationController.interactivePopGestureRecognizer?.isEnabled = true;
    }
    else
    {
         self.navigationController?.interactivePopGestureRecognizer?.delegate = nil
        navigationController.interactivePopGestureRecognizer?.isEnabled = false;
    }
}

Just don't forget to add UINavigationControllerDelegate and set the navigationController?.delegate = self Another important part is to assign the interactivePopGestureRecognizer to self or to nil accordingly.


We have faced the same problem couple of weeks back. And for our problem we narrowed it down to left-edge pop gesture recogniser. You can try and check if you can reproduce this problem using below steps

  • Try using the left edge pop gesture when there are no view controllers below it (i.e on root view controllers, your VC-Home controller)
  • Try clicking on any UI elements after this.

If you are able to reproduce the freeze, try disabling the interactivePopGestureRecognizer when the view controller stack have only one view controller.

Refer to this question for more details. Below is the code from the link for ease of reference.

- (void)navigationController:(UINavigationController *)navigationController
   didShowViewController:(UIViewController *)viewController
                animated:(BOOL)animate
{
    if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
{
        if (self.viewControllers.count > 1)
        {
            self.interactivePopGestureRecognizer.enabled = YES;
        }
        else
        {
            self.interactivePopGestureRecognizer.enabled = NO;
        }
    }
}

I was thinking about intermittently freezing, main thread and SDWebImage.

Assuming that you using the image you downloaded from downloadImageWithURL:options:progress:completed:'s completed block .. if so, make sure you dispatch to the main queue before using using the image.

If you use the SDWebImageDownloader directly, the completion block (as you noted) will be invoked on a background queue, you can fix it using dispatch_async on the main queue from the completion.

Otherwise you can use: SDWebImageManager downloadImageWithURL:options:progress:completed: (method that invokes the completion blocks on the main queue).

if the problem persist (just because you speaking about "..some unique things about my app is that it is very image heavy..") look also Common problems expecially the Handle image refresh know problems.

Add to your check also this nice snippet code:

import UIKit.UINavigationController

public typealias VoidBlock = (Void -> Void)

public extension UINavigationController  
{
    public func pushViewController(viewController: UIViewController, animated: Bool, completion: VoidBlock) {
        CATransaction.begin()
        CATransaction.setCompletionBlock(completion)
        self.pushViewController(viewController, animated: animated)
        CATransaction.commit()
    }
}

maybe can help to understand if pushViewController finish, if finish with all viewControllers expected ..

Another test I try to make is to launch the app with iOS 8.x and iPhone 6+, because there are some issues in the pureLayout project around iOS 9. Can you send feedbacks around this test?

I've some suspicious also on the real scrollview dimension before the pushview action, can you analyze the current view by examing the view hierarchy?