【问题标题】:Slide gesture with custom back button freezes the root view controller带有自定义后退按钮的滑动手势冻结根视图控制器
【发布时间】:2014-02-26 19:30:38
【问题描述】:

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

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

有什么建议吗?

【问题讨论】:

  • 那个链接失效了?

标签: ios7 uinavigationcontroller


【解决方案1】:

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

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

【讨论】:

  • 这应该被标记为正确答案 - 只有一个适用于所有情况。
【解决方案2】:

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

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

【讨论】:

  • 那行不通——当你在动画发生时继续滑动仍然会导致卡顿
【解决方案3】:

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

@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{
//}

【讨论】:

  • 嘿阿南德,我之前已经尝试过上面的代码,它确实使情况好一些。但是当你从导航堆栈中推送和弹出很多时,屏幕仍然会冻结。
【解决方案4】:

这是我对here提出的类似问题的回答

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

- (NSArray*)leftBarButtonItems
{
    return nil;
}

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

【讨论】:

    【解决方案5】:

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

    【讨论】:

      猜你喜欢
      • 2023-03-27
      • 1970-01-01
      • 1970-01-01
      • 2016-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-23
      相关资源
      最近更新 更多