一句话笔记(24)(连续 Push)

字数 603阅读 235

一句话笔记,某段时间内遇到或看到的某个可记录的点。 2017-05-09

  • 1、如何确定是 Tab 切换的页面 还是 Pop 回来的页面
  • 2、解决在某些情况下出现连续 Push 的情况的 BUG

一、如何确定是 Tab 切换的页面 还是 Pop 回来的页面

  • 思路一: 从 UITabBarControllerDelegate 处判断
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UINavigationController *)viewController {
    if ([viewController.topViewController isKindOfClass:TestViewController.class]) {
        TestViewController *testVC = (TestViewController *)viewController.topViewController;
        testVC.isTabBarSwitch = YES;
    }
    return YES;
}
  • 思路二: 从 重写 UINavigationController Pop 判断
- (UIViewController *)popViewControllerAnimated:(BOOL)animated {
    self.isPop = YES;
    return [super popViewControllerAnimated:animated];
}

然后想了下,还是选择了思路二,毕竟这样假如后期其他 ViewController 也有用到其的时候,方便扩展。

二、解决在某些情况下出现连续 Push 的情况的 BUG

有时候,我们在网络条件比较差的情况下,容易出现那种连续 Push 的情况,让人很烦。

  • 解决方案一:在其代理中通过一个 临时变量 判断
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
    if (self.isSwitching) {
        return;
    }
    self.isSwitching = YES;
    [super pushViewController:viewController animated:animated];
}

//- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
//    self.isSwitching = YES;
//}

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    self.isSwitching = NO;
}

注意下面那个方法是代理呈现出来的。

  • 解决方案二: 通过判断当前 ViewController 来解决
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
    // 判断上一个控制器和现在的控制器是不是同一个
    if ([self.topViewController isMemberOfClass:[viewController class]]) {
        return;
    }
    [super pushViewController:viewController animated:animated];
}

通常情况下,解决 网络比较差的情况下出现的连续 Push, 个人认为采取方案二解决。

PS: 防止触摸事件触发新方法的一个系统方法。


//开始禁止交互  
- (void)beginIgnoringInteractionEvents; 
//结束禁止交互  
- (void)endIgnoringInteractionEvents;  
//是否禁止了交互  
- (BOOL)isIgnoringInteractionEvents;    

所以此处在某些 Target-Action 处也可以直接,防止在这个过程中的第二次交互:

- (IBAction)testAction:(id)sender {
    [[UIApplication sharedApplication] beginIgnoringInteractionEvents];
    // Do Some
    FirstViewController * firstVC = [[FirstViewController alloc] init];
    [self.navigationController pushViewController:firstVC animated:YES];
    
    [[UIApplication sharedApplication] endIgnoringInteractionEvents];
}

但是实际上这样是不能很好的解决的 连续Push 的过程,它只是保证在每一次 Action 的时候外部禁止交互, 而网络环境比较弱的时候,这个过程都还没开始,却被执行了多遍 Action, 从而其实上并没有解决这个问题。所以,此处有待商榷。

所以,目前个人暂时比较认同方案二的, 简单直接。

  • 当然如果项目中出现一个类真需连续调用的情况,那就另当别论。别说,还真有这种情况。
  • 而采用方案一也有一个问题,当其是 RootViewController 的时候, 那个 方法会走两次,所以也无效。
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated;

于是最终,我是为了解决 网络条件差的情况下,偶尔出现的连续 Push ,所以我采用两者合一。

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
    // 对于同一个 ViewController 防止连续 Push
    if ([self.topViewController isMemberOfClass:[viewController class]]) {
        if (self.isSwitching) {
            return;
        }
        self.isSwitching = YES;
    }
    [super pushViewController:viewController animated:animated];
}

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    self.isSwitching = NO;
}

备注参考:
http://blog.lessfun.com/blog/2015/09/09/uiviewcontroller-push-pop-trap/

推荐阅读更多精彩内容