iOS项目之“返回”手势操作相关

    在程序中,总会设置“返回”按钮,但不可能在每一个控制器中都去设置一次“返回”按钮,那如何设置全局的“返回”按钮呢?

    首先自定义一个导航控制器,在tabBarController中添加子控制器时,使用这个自定义的导航控制器,所以在这个导航控制器中重写push方法设置“返回”按钮就可以了。

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    // 如果是根控制器,则不需要添加“返回”按钮
    if (self.childViewControllers.count > 0) {
        viewController.navigationItem.leftBarButtonItem = [UIBarButtonItem wx_itemBackWithTarget:self action:@selector(backClick)];
        viewController.hidesBottomBarWhenPushed = YES;
    }
    [super pushViewController:viewController animated:animated];
}

    需要注意的是,如果自己设置了“返回”按钮,那么系统的边缘滑动返回功能就失效了,这是为什么呢?

    边缘滑动返回功能失效的原因:

        1>分析:边缘滑动功能属于手势操作,在UINavigationController中找到手势属性,打印输出看手势是否被清空

@property(nullable, nonatomic, readonly) UIGestureRecognizer *interactivePopGestureRecognizer NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED;
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    if (self.childViewControllers.count > 0) {
        viewController.navigationItem.leftBarButtonItem = [UIBarButtonItem wx_itemBackWithTarget:self action:@selector(backClick)];
        viewController.hidesBottomBarWhenPushed = YES;

        // 输出手势
        WXLog(@"%@",self.interactivePopGestureRecognizer);
    }
    [super pushViewController:viewController animated:animated];
}

        输出结果:

2016-05-20 14:15:39.874 caravan-alter[3652:128235] <UIScreenEdgePanGestureRecognizer: 0x7f80c9e80860; state = Possible; delaysTouchesBegan = YES; view = <UILayoutContainerView 0x7f80c9e53d50>; target= <(action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7f80c9ea1ad0>)>>

        结论:手势并没有被清空,所以排除手势被清空的可能。

        2>分析:手势代理做了一些事情,导致手势失效

        在viewDidLoad中输入以下代码:

self.interactivePopGestureRecognizer.delegate = nil;

        结论:将代理清空时,边缘滑动手势恢复,但出现的问题是,如果在根控制器继续使用边缘滑动手势操作,那么在下一次push的时候会出现程序假死的情况。将代理清空

        解决:将代理设置为self,判断手势是否恢复,只需要判断在根控制器下,不需要滑动手势即可。

// 两个方法都可以,二选一即可
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
    return self.childViewControllers.count > 1;
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    return self.childViewControllers.count > 1;
}

    为了给用户更好的体验效果,可以给程序添加全屏滑动效果。

    实现:根据打印输出边缘滑动手势,不难发现一些东西:

  UIScreenEdgePanGestureRecognizer:屏幕边缘手势

  target=<_UINavigationInteractiveTransition 0x7f80c9ea1ad0>

  action=handleNavigationTransition:

    有了这些信息,只需要找到_UINavigationInteractiveTransition这个类就可以了,当设置手势代理之前打印输出self.interactivePopGestureRecognizer.delegate,可以发现手势代理就是这个类,实现代码:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self.interactivePopGestureRecognizer.delegate action:@selector(handleNavigationTransition:)];
    // 判断手势什么时候触发
    pan.delegate = self;
    // 添加手势
    [self.view addGestureRecognizer:pan];
    
    // 添加了全屏手势,边缘手势就没什么用了
//    self.interactivePopGestureRecognizer.delegate = self;
}

    全屏手势就这样实现了!

原文地址:https://www.cnblogs.com/sjxjjx/p/5512173.html