一句话笔记,某段时间内遇到或看到的某个可记录的点。 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/
网友评论
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;
}
这两个方法都是代理体现出来的吗?
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
self.isSwitching = NO;
}
这个方法什么时候调用啊
后者是代理方法,当你有 Push 跳转成功后就调用啊
这个直接看 其 Api 就知道了