Slide gesture with custom back button freezes the

2019-04-09 13:16发布

I have custom back buttons all over my app and it looks like navigation controller does not like it.

So, I want the iOS7 swipe-to-go-back gesture to work along with my custom back buttons. Searched and tried different ways but none seems to be promising. The closest I could get is with http://keighl.com/post/ios7-interactive-pop-gesture-custom-back-button/. However, Now when I keep pushing and popping the navigation stack, after sometime the rootViewController in the stack stops responding to any touch.

Any suggestions?

5条回答
霸刀☆藐视天下
2楼-- · 2019-04-09 13:53

Even I had the same problem, I have fix it by modifying code provide in the link which you are referring . Now My screens freezes very rarely still finding for permanent fix.

@implementation PPNavigationController

-(void)viewDidLoad
{
    //[super viewDidLoad];
    // Do any additional setup after loading the view.

     __weak PPNavigationController *weakSelf = self;

    if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
    {
        self.interactivePopGestureRecognizer.delegate = weakSelf;
        self.delegate = weakSelf;
    }

}



-(void)navigationController:(UINavigationController *)navigationController
       didShowViewController:(UIViewController *)viewController
                    animated:(BOOL)animate
{
    // Enable the gesture again once the new controller is shown

    if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
        self.interactivePopGestureRecognizer.delegate = viewController;
}

Don't use this method
//-(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{
//}
查看更多
我命由我不由天
3楼-- · 2019-04-09 13:57

Subclassing UINavigationController, like keighl is suggesting, is the right approach imo. But he's missing a check for the root view controller to avoid freezing when the gesture is executed on the root view. Here's a modified version with the additional check:

CBNavigationController.h:

#import <UIKit/UIKit.h>

@interface CBNavigationController : UINavigationController <UIGestureRecognizerDelegate, UINavigationControllerDelegate>
@end

CBNavigationController.m:

#import "CBNavigationController.h"

@interface CBNavigationController ()
@end

@implementation CBNavigationController
- (void)viewDidLoad
{
    NSLog(@"%s",__FUNCTION__);
    __weak CBNavigationController *weakSelf = self;

    if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
    {
        self.interactivePopGestureRecognizer.delegate = weakSelf;
        self.delegate = weakSelf;
    }
}

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    NSLog(@"%s",__FUNCTION__);

    if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
        self.interactivePopGestureRecognizer.enabled = NO;

    [super pushViewController:viewController animated:animated];
}

#pragma mark UINavigationControllerDelegate

- (void)navigationController:(UINavigationController *)navigationController
       didShowViewController:(UIViewController *)viewController
                    animated:(BOOL)animate
{
    NSLog(@"%s",__FUNCTION__);

    // Enable the gesture again once the new controller is shown AND is not the root view controller
    if (viewController == self.viewControllers.firstObject)
    {
        if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
            self.interactivePopGestureRecognizer.enabled = NO;
    }
    else
    {
        if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
            self.interactivePopGestureRecognizer.enabled = YES;
    }
}

@end

查看更多
▲ chillily
4楼-- · 2019-04-09 14:02

Here's a simple Swift subclass of UINavigationController you can use that I adapted from @weak's answer. There shouldn't be a need to implement UIGestureRecognizerDelegate as the nav delegate's navigationController(_:didShow:animated:) handles the work of enabling and disabling the pop gesture.

Using this subclass in your storyboard or code is easier than doing a one-off disabling in your other controllers that are embedded in nav controllers.

import UIKit

@objc class LWNavigationController : UINavigationController,
                                     UINavigationControllerDelegate {
    override func viewDidLoad() {
        self.delegate = self
    }

    override func pushViewController(_ viewController: UIViewController,
                                     animated: Bool) {
        // Disable this gesture while animating a push.
        self.interactivePopGestureRecognizer?.isEnabled = false
        super.pushViewController(viewController, animated: animated)
        debugPrint("------\(#function) \(viewController)------")
    }

    // MARK: - UINavigationControllerDelegate

    func navigationController(_ navigationController: UINavigationController,
                              didShow viewController: UIViewController,
                              animated: Bool) {
        if (viewController == self.viewControllers.first) {
            // Keep the gesture disabled if we're at the root to avoid back swipes
            // from corrupting the navigation stack.
            self.interactivePopGestureRecognizer?.isEnabled = false
        } else {
            self.interactivePopGestureRecognizer?.isEnabled = true
        }
        debugPrint("------\(#function) \(viewController) " +
                   "enabled: \(self.interactivePopGestureRecognizer?.isEnabled)" +
                   "------")
    }
}
查看更多
Bombasti
5楼-- · 2019-04-09 14:07

I've got the same problem, here is my solution: In your custom NavigationController, like MYNavigationController, cause you set the gesture delegate to the navigationController, you can add the delegate method there :

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
    if (self.viewControllers.count>1) {
        return YES;
    }
    return NO;
}
then it will stop the poping action when it's in the root viewController and avoiding the freezing behavior.

查看更多
聊天终结者
6楼-- · 2019-04-09 14:08

Here is my answer to a similar question asked here

You can use a little trick to get the native gesture working. Create a subclass of UINavigationItem, then override leftBarButtonItems method:

- (NSArray*)leftBarButtonItems
{
    return nil;
}

Now use this class for the item that has custom left UIBarButtonItem. The gesture works! This is because UINavigationController thinks there are no left items and enables the gesture. You are still able to access your custom item through the leftBarButtonItem property.

查看更多
登录 后发表回答