使用自定义后退按钮滑动手势会冻结根视图控制器

时间:2014-02-26 19:30:38

标签: ios7 uinavigationcontroller

我的应用程序遍布自定义后退按钮,看起来导航控制器不喜欢它。

所以,我希望iOS7的滑动到后退手势与我的自定义后退按钮一起工作。搜索并尝试了不同的方式,但似乎没有一个很有希望。我能得到的最接近的是http://keighl.com/post/ios7-interactive-pop-gesture-custom-back-button/。 但是,现在当我继续推送并弹出导航堆栈时,堆栈中的rootViewController会停止响应任何触摸。

有什么建议吗?

5 个答案:

答案 0 :(得分:4)

像keighl建议的那样,对UINavigationController进行子类化是正确的方法。但他错过了对根视图控制器的检查,以避免在根视图上执行手势时冻结。 这是一个带有附加检查的修改版本:

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

答案 1 :(得分:1)

我遇到了同样的问题,这是我的解决方案: 在您的自定义NavigationController中,如MYNavigationController,因为您将手势委托设置为navigationController,您可以在那里添加委托方法:

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
    if (self.viewControllers.count>1) {
        return YES;
    }
    return NO;
}
然后它将在根视图控制器中停止弹出操作并避免冻结行为。

答案 2 :(得分:0)

即使我遇到了同样的问题,我也通过修改您所指的链接中提供的代码来修复它。现在我的屏幕冻结很少,仍然找到永久修复。

@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 :(得分:0)

以下是我对here

提出的类似问题的回答

您可以使用一个小技巧来使本机手势正常工作。 创建UINavigationItem的子类,然后覆盖leftBarButtonItems方法:

- (NSArray*)leftBarButtonItems
{
    return nil;
}

现在将此类用于具有自定义左UIBarButtonItem的项目。手势有效!这是因为UINavigationController认为没有剩下的项目并启用了手势。您仍然可以通过leftBarButtonItem属性访问自定义项目。

答案 4 :(得分:0)

这是一个简单的UINavigationController的Swift子类,你可以使用我改编自@ weak的答案。由于导航委托UIGestureRecognizerDelegate处理启用和禁用弹出手势的工作,因此不需要实施navigationController(_:didShow:animated:)

在故事板或代码中使用此子类比在导航控制器中嵌入的其他控制器中进行一次性禁用更容易。

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)" +
                   "------")
    }
}