2014年4月份第一次接觸IOS端開(kāi)發(fā),為某銀行開(kāi)發(fā)一款金融app。
在開(kāi)發(fā)的最后階段,加入了需要從任意一個(gè)頁(yè)面直接返回主頁(yè)的功能。
悲催的是,當(dāng)時(shí)沒(méi)有使用UINavigationController進(jìn)行導(dǎo)航管理,而是使用了IOS中的模態(tài)跳轉(zhuǎn)方式(presentViewController/dismissViewControllerAnimated).

因此需要找的一種方法進(jìn)行,實(shí)現(xiàn)如下方式的導(dǎo)航跳轉(zhuǎn):
面對(duì)上面的需求,最簡(jiǎn)單的方式是將所有控制器都改成UINavigationController,并且利用pushViewController / popToViewController/ popToRootViewControllerAnimated 等方法進(jìn)行完美解題。但是當(dāng)時(shí)項(xiàng)目的頁(yè)面將近100個(gè),分成三大模塊,需要大規(guī)模修改設(shè)計(jì)頁(yè)面以及調(diào)整大量代碼,這并不是一個(gè)現(xiàn)實(shí)的解決方案,不到萬(wàn)不得已,不能采取如此低劣手段!
我們需要一個(gè)滿足如下條件的解決方案:
1) 對(duì)于已經(jīng)在InterfaceBuilder中完成的頁(yè)面,不做任何修改 2) 盡量少的修改代碼,因?yàn)楹芏啻a已經(jīng)經(jīng)過(guò)測(cè)試中心測(cè)試過(guò),如果修改,需要全部重新測(cè)試,時(shí)間來(lái)不及。
當(dāng)時(shí)通過(guò)兩天的研究,深入的了解了IOS中的跳轉(zhuǎn)流程和生命周期后,找到了一個(gè)相對(duì)完美的解決方案,能夠滿足上面提到的要求。通過(guò)一個(gè)Demo,來(lái)和大家一起分享。
1) 為了減少代碼的修改,增加一個(gè)基類。
@interface BaseViewController : UIViewController //防止controller循環(huán)引用,使用weak引用方式 @property(nonatomic,weak) BaseViewController* parentController; //為了能夠了解某個(gè)頁(yè)面控制器生命周期相關(guān)信息,給該控制器取個(gè)名字 @property(nonatomic,copy) NSString* ctrlName; //關(guān)鍵的函數(shù),進(jìn)行頁(yè)面c-->跳轉(zhuǎn)到主頁(yè) -(void) doDismiss; @end
2) 為了更好的了解IOS中ViewController的生命周期,我們?cè)诨愔休敵鱿嚓P(guān)信息來(lái)了解生命周期相關(guān)信息。
@implementation BaseViewController
-(id) init
{
self.ctrlName = @"";
self.parentController = nil;
return [super init];
}
- (void)viewDidLoad
{
NSLog(@"%@ invoke viewDidLoad",self.ctrlName);
[super viewDidLoad];
// Do any additional setup after loading the view.
}
-(void)viewWillAppear:(BOOL)animated
{
NSLog(@"%@ invoke viewWillAppear",self.ctrlName);
[super viewWillAppear:animated];
}
-(void)viewDidAppear:(BOOL)animated
{
NSLog(@"%@ invoke viewDidAppear",self.ctrlName);
[super viewDidAppear:animated];
}
-(void) viewWillDisappear:(BOOL)animated
{
NSLog(@"%@ invoke viewWillDisappear",self.ctrlName);
[super viewWillDisappear:animated];
}
-(void) viewDidDisappear:(BOOL)animated
{
NSLog(@"%@ invoke viewDidDisappear",self.ctrlName);
[super viewDidDisappear:animated];
}
- (void)didReceiveMemoryWarning
{
NSLog(@"%@ invoke didReceiveMemoryWarning",self.ctrlName);
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)dealloc
{
NSLog(@"%@ .......dealloc.......",self.ctrlName);
}3) 關(guān)鍵的遞歸函數(shù),核心是理解dismissViewControllerAnimated:completion函數(shù)中completion回調(diào)的時(shí)機(jī)點(diǎn),這個(gè)是解題的鑰匙。
-(void)doDismiss
{
NSLog(@"%@ dismiss begin",self.ctrlName);
if([self.parentController isKindOfClass:[ViewController class]])
{
[self dismissViewControllerAnimated:YES completion: ^(void)
{
NSLog(@"%@ dismiss end",self.ctrlName);
if(self.parentController)
{
[self.parentController doDismiss];
}
}];
}
else
{
[self dismissViewControllerAnimated:NO completion: ^(void)
{
NSLog(@"%@ dismiss end",self.ctrlName);
if(self.parentController)
{
[self.parentController doDismiss];
}
}];
}
}4) Demo頁(yè)面結(jié)構(gòu)如下圖: MainViewController-->SecondViewController-->Child1ViewController,然后直接跳回到MainViewController. 5) 所有的ViewController都繼承自我們自定義的BaseViewController,具有關(guān)鍵的doDismiss遞歸方法!

6) 看一下從MainViewController-->SecondViewController-->Child1ViewController-->MainViewController生命周期的相關(guān)信息:
a、啟動(dòng)程序,進(jìn)入MainViewController:
2017-02-11 17:25:16.964 navTest[933:17086] mainViewCtrl invoke viewDidLoad
2017-02-11 17:25:16.966 navTest[933:17086] mainViewCtrl invoke viewWillAppear
2017-02-11 17:25:16.975 navTest[933:17086] mainViewCtrl invoke viewDidAppear
b、從MainViewController→SecondViewController:
2017-02-11 17:28:29.717 navTest[933:17086] SecondViewController invoke viewDidLoad [先newController調(diào)用viewDidLoad]
2017-02-11 17:28:29.721 navTest[933:17086] mainViewCtrl invoke viewWillDisappear [然后oldController調(diào)用viewWillDisappear]
2017-02-11 17:28:29.722 navTest[933:17086] SecondViewController invoke viewWillAppear [然后newController調(diào)用viewWillAppear]
2017-02-11 17:28:30.229 navTest[933:17086] SecondViewController invoke viewDidAppear [然后newController調(diào)用viewDidAppear ]
2017-02-11 17:28:30.229 navTest[933:17086] mainViewCtrl invoke viewDidDisappear [然后oldController調(diào)用viewDidDisappear ]
2017-02-11 17:28:30.230 navTest[933:17086] mainViewCtrl present end
[最后oldController調(diào)用presentViewController完成回調(diào)被調(diào)用]
下面是presentViewController完成回調(diào)信息的輸出代碼,用來(lái)了解completion是在哪個(gè)階段被調(diào)用的,很重要的信息哦!!!
- (IBAction)ClickToEnterSecondController:(id)sender {
SecondViewController* ctrl = [self.storyboard instantiateViewControllerWithIdentifier:@"second"];
ctrl.parentController = self;
ctrl.ctrlName = @"SecondViewController";
[self presentViewController:ctrl animated:YES completion:^(void)
{
NSLog(@"%@ present end",self.ctrlName);
}];
}c、從Child1ViewController直接返回到MainViewController的流程(跳過(guò)SecondViewController)
- (IBAction)returnMainViewController:(id)sender {
NSLog(@"**********************doDismiss*********************");
[self doDismiss];
}d、2017-02-11 17:30:30.634 navTest[933:17086] **doDismiss* [要開(kāi)始調(diào)用doDismiss函數(shù)了,表示點(diǎn)擊了返回按鈕]
2017-02-11 17:30:30.635 navTest[933:17086] Child1ViewController dismiss begin [輸出dismiss begin,表示調(diào)用了Child1ViewController的doDismiss遞歸函數(shù)]
2017-02-11 17:30:30.637 navTest[933:17086] Child1ViewController invoke viewWillDisappear [oldController viewWillDisappear]
2017-02-11 17:30:30.638 navTest[933:17086] SecondViewController invoke viewWillAppear [newController viewWillAppear]
2017-02-11 17:30:30.641 navTest[933:17086] SecondViewController invoke viewDidAppear [newController viewDidAppear]
2017-02-11 17:30:30.641 navTest[933:17086] Child1ViewController invoke viewDidDisappear [oldController viewDidDisappear ]
2017-02-11 17:30:30.641 navTest[933:17086] Child1ViewController dismiss end [關(guān)鍵時(shí)刻哦,oldController self dismissViewControllerAnimated: completion: 中的completion 回調(diào)被觸發(fā)了,它是在 oldController viewDidDisappear后被觸發(fā)的哦]
2017-02-11 17:30:30.641 navTest[933:17086] SecondViewController dismiss begin [這時(shí)候,從ChildViewController回彈到SecondViewController的流程完成了,接下來(lái)遞歸調(diào)用,要完成從SecondViewController回彈到MainViewController的過(guò)程,重復(fù)上面的流程而已]
2017-02-11 17:30:30.642 navTest[933:17086] Child1ViewController …….dealloc……. [Child1ViewController已經(jīng)完全消失了,因此內(nèi)存被析構(gòu)了,這樣確保內(nèi)存不會(huì)泄露哦]
2017-02-11 17:30:30.643 navTest[933:17086] SecondViewController invoke viewWillDisappear
2017-02-11 17:30:30.644 navTest[933:17086] mainViewCtrl invoke viewWillAppear
2017-02-11 17:30:31.156 navTest[933:17086] mainViewCtrl invoke viewDidAppear
2017-02-11 17:30:31.156 navTest[933:17086] SecondViewController invoke viewDidDisappear
2017-02-11 17:30:31.156 navTest[933:17086] SecondViewController dismiss end
2017-02-11 17:30:31.157 navTest[933:17086] mainViewCtrl dismiss begin
2017-02-11 17:30:31.157 navTest[933:17086] SecondViewController …….dealloc……. [SecondViewController 內(nèi)存也很完美的被析構(gòu)掉,目前僅剩下MainViewController還活著]
show一下某銀行APP以前模擬器中的效果截圖,IOS開(kāi)發(fā)還是非常令人非常愉悅的感覺(jué)!

×××:
IOS UIViewController 導(dǎo)航及生命周期Demo
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。
網(wǎng)頁(yè)名稱:IOS視圖控制器導(dǎo)航及生命周期研究Demo-創(chuàng)新互聯(lián)
文章位置:http://chinadenli.net/article32/edssc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信小程序、外貿(mào)網(wǎng)站建設(shè)、網(wǎng)站排名、網(wǎng)站導(dǎo)航、定制開(kāi)發(fā)、App設(shè)計(jì)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容