1,背景:
2014年4月份第一次接触IOS端开发,为某银行开发一款金融应用。
在开发的最后阶段,加入了需要从任意一个页面直接返回主页的功能。
悲催的是,当时没有使用UINavigationController进行导航管理,而是使用了IOS中的模态跳转方式(<强> presentViewController/dismissViewControllerAnimated 强>)。
因此需要找的一种方法进行,实现如下方式的导航跳转:
已知:页面一个→页面b→页面c
求解:页面c直接跳回到页面,并且要求不能有内存泄露,循环依赖等
2,解题思考:
面对上面的需求,最简单的方式是将所有控制器都改成UINavigationController,并且利用<强> pushViewController/popToViewController popToRootViewControllerAnimated 强>等方法进行完美解题。但是当时项目的页面将近100个,分成三大模块,需要大规模修改设计页面以及调整大量代码,这并不是一个现实的解决方案,不到万不得已,不能采取如此低劣手段!
我们需要一个满足如下条件的解决方案:
1),对于已经在InterfaceBuilder中完成的页面,不做任何修改 2),尽量少的修改代码,因为很多代码已经经过测试中心测试过,如果修改,需要全部重新测试,时间来不及。
当时通过两天的研究,深入的了解了IOS中的跳转流程和生命周期后,找到了一个相对完美的解决方案,能够满足上面提到的要求。通过一个演示,来和大家一起分享。
3,解题流程:
1),为了减少代码的修改,增加一个基类。
@interface BaseViewController : ui//防止控制器循环引用,使用弱引用方式 @ property(原子、弱),BaseViewController *, parentController;//为了能够了解某个页面控制器生命周期相关信息,给该控制器取个名字 @ property(原子、复制),,,NSString *,,, ctrlName;//关键的函数,进行页面c,在跳转到主页 (空白),doDismiss; @end以前> <>前2),为了更好的了解IOS中ViewController的生命周期,我们在基类中输出相关信息来了解生命周期相关信息。
@implementation BaseViewController - (id),初始化 { ,,,self.ctrlName =, @ "; ,,,self.parentController =,零; ,,,return [super init]; } 安康;viewDidLoad (void) { ,,,NSLog (@ % @ invoke  viewDidLoad, self.ctrlName); ,,,(super viewDidLoad); ,,,//,Do any additional setup after loading 从而视图。 } - (void)那些:(BOOL)动画 { ,,,NSLog (@ % @ invoke 那些,self.ctrlName); ,,,(super 那些:动画); } - (void) viewDidAppear: (BOOL)动画 { ,,,NSLog (@ % @ invoke  viewDidAppear, self.ctrlName); ,,,(super viewDidAppear:动画); } (空白),viewWillDisappear: (BOOL)动画 { ,,,NSLog (@ % @ invoke  viewWillDisappear, self.ctrlName); ,,,(super viewWillDisappear:动画); } (空白),viewDidDisappear: (BOOL)动画 { ,,,NSLog (@ % @ invoke viewDidDisappear, self.ctrlName); ,,,(super viewDidDisappear:动画); } 安康;didReceiveMemoryWarning (void) { ,,,NSLog (@ % @ invoke didReceiveMemoryWarning, self.ctrlName); ,,,(super didReceiveMemoryWarning); ,,,//,Dispose of any resources that 还要be 重新创建。 } - (void) dealloc { ,,,NSLog (@“% @ ....... dealloc .......”, self.ctrlName); }
3),关键的递归函数,核心是理解dismissViewControllerAnimated:完成函数中完成回调的时机点,这个是解题的钥匙。
- (void) doDismiss { ,,,NSLog (@ % @ dismiss 开始,self.ctrlName); ,,,如果([self.parentController isKindOfClass: [ViewController 类]]) ,,,{ ,,,,,,,(self dismissViewControllerAnimated: YES 完成:^(空白) ,,,,,,,,{ ,,,,,,,,,,,,NSLog (@ % @ dismiss 最终,self.ctrlName); ,,,,,,,,,,,,如果(self.parentController) ,,,,,,,,,,,,{ ,,,,,,,,,,,,,,,,(self.parentController doDismiss); ,,,,,,,,,,,,} ,,,,,,,,}]; ,,,} ,,, ,,,{ ,,,,,,,(self dismissViewControllerAnimated: NO 完成:^(空白) ,,,,,,,,{ ,,,,,,,,,,,,NSLog (@ % @ dismiss 最终,self.ctrlName); ,,,,,,,,,,,,如果(self.parentController) ,,,,,,,,,,,,{ ,,,,,,,,,,,,,,,,(self.parentController doDismiss); ,,,,,,,,,,,,} ,,,,,,,,}]; ,,,} null null null null null null null null null null null null null nullIOS视图控制器导航及生命周期研究演示