iOS实战之页面跳转
假如有多级页面Root->A->B->C的跳转,现需要从C返回到A,做法有如下:
有人可能会说,直接pop两下就好了,like this:❎错误姿势❌:
//C.m - (void)back { [self.navigationController popViewControllerAnimated:NO]; //pop到B [self.navigationController popViewControllerAnimated:YES]; //pop到A }
可以试一试,要是能达到效果算我输!!!pop到B以后self.navigationController=nil,可以想想是为什么?(页面pop出去了,导航栏当然也跟着出去了,所以下面这个pop根本不起作用)
✅正确姿势一:由上面错误姿势得到启发,第二个pop不是不起作用吗,那就让B页面去做pop,通知,代理,block都行
//C.h // 定义Block typedef void(^BackBlock)(void); @property(nonmatic,copy) BackBlock backBlock; //C.m // 返回事件 - (void)back { [self.navigationController popViewControllerAnimated:NO]; if(self.backBlock) { self.backBlock(); } }
//B.m C *c = [C new]; c.backBlock = ^{ //让B来执行回调,pop页面 [self.navigationController popViewControllerAnimated:NO]; }; [self.navigationController pushViewController:c animated:YES];
总结:虽然能实现,但是很麻烦,还需要写清动画YES还是NO,不然pop几个都有动画的页面会很突兀。
✅正确姿势二:利用导航栈的特性,去除导航栈上面的页面
- (void)back { // 获取所有的控制器数组 NSMutableArray *vcArr = [NSMutableArray arrayWithArray:self.navigationController.viewControllers]; // 直接将上级页面从数组中移除 [vcArr removeObjectAtIndex:vcArr.count-2]; self.navigationController.viewControllers = vcArr; [self.navigationController popViewControllerAnimated:NO]; }
✅正确姿势三:与第二个类似,但是是从导航栈获取vc
- (void)back { NSInteger num = self.navigationController.viewControllers.count; if (num > 3) { UIViewController *popVC = self.navigationController.viewControllers[num - 3]; //直接拿到A的vc [self.navigationController popToViewController:popVC animated:YES]; } }
个人推荐使用第三种方法,第二种方法直接去除导航栈上面的页面,怕出现问题,而第三种方式是拿页面(读比写操作安全)。