1、引言
作為MVC設計形式中的C,Controller一向飾演著項目開辟中最主要的腳色,它是視圖和數據的橋梁,經由過程它的治理,將數據頭頭是道的展現在我們的View層上。IOS中的UIViewController是UIKit框架中最根本的一個類。從第一個UI視圖到龐雜完全項目,都離不開UIViewController作為基本。基於UIViewController的封裝和擴大,也可以或許精彩的完成各類龐雜界面邏輯。這裡旨在評論辯論UIViewController的性命周期和屬性辦法,在最基本的器械上,常常會獲得意想不到的欣喜。
2、UIViewController的性命周期
要懂得UIViewController,先要弄清晰其性命周期。在面向對象的說話中,是對象,就必定要有性命周期,UIViewController也不破例,性命周期治理Controller的感化規模和時光,也治理其內對象的感化規模和時光。起首,UIViewController中與其性命周期有關的幾個函數以下:
//類的初始化辦法
下面這麼多的函數,乍一看甚麼龐雜,其實關系甚麼晴明,除initialize,init和initWithCoder不是存在一切對象的聲明周期中,其他函數都邑在UIViewController的聲明周期中有序的被挪用。那末詳細的挪用次序是如何的呢,最好的方法是理論一下,經由過程編號打印,成果以下:
+ (void)initialize;
//對象初始化辦法
- (instancetype)init;
//從歸檔初始化
- (instancetype)initWithCoder:(NSCoder *)coder;
//加載視圖
-(void)loadView;
//將要加載視圖
- (void)viewDidLoad;
//將要結構子視圖
-(void)viewWillLayoutSubviews;
//曾經結構子視圖
-(void)viewDidLayoutSubviews;
//內存正告
- (void)didReceiveMemoryWarning;
//曾經展現
-(void)viewDidAppear:(BOOL)animated;
//將要展現
-(void)viewWillAppear:(BOOL)animated;
//將要消逝
-(void)viewWillDisappear:(BOOL)animated;
//曾經消逝
-(void)viewDidDisappear:(BOOL)animated;
//被釋放
-(void)dealloc;
這是一個ViewController完全的聲明周期,其實外面還有很多多少處所須要我們留意一下:
1:initialize函數其實不會每次創立對象都挪用,只要在這個類第一次創立對象時才會挪用,做一些類的預備任務,再次創立這個類的對象,initalize辦法將不會被挪用,關於這個類的子類,假如完成了initialize辦法,在這個子類第一次創立對象時會挪用本身的initalize辦法,以後不會挪用,假如沒有完成,那末它的父類將替它再次挪用一下本身的initialize辦法,今後創立也都不會再挪用。是以,假如我們有一些和這個相干的全局變量,可以在這裡停止初始化。
2:init辦法和initCoder辦法類似,只是被挪用的情況紛歧樣,假如用代碼停止初始化,會挪用init,從nib文件或許歸檔停止初始化,會挪用initCoder。
3:loadView辦法是開端加載視圖的肇端辦法,除非手動挪用,不然在ViewController的性命周期中沒特別情形只會被挪用一次。
4:viewDidLoad辦法是我們最經常使用的辦法的,類中成員對象和變量的初始化我們都邑放在這個辦法中,在類創立後,不管視圖的展示或消逝,這個辦法也是只會在將要結構時挪用一次。
5:viewWillAppear:視圖將要展示時會挪用。
6:viewWillLayoutSubviews:在viewWillAppear後挪用,將要對子視圖停止結構。
7:viewDidLayoutSubviews:曾經結構完成子視圖。
8:viewDidAppare:視圖完成顯示時挪用。
9:viewWillDisappear:視圖將要消逝時挪用。
10:viewDidDisappear:視圖曾經消逝時挪用。
11:dealloc:controller被釋放時挪用。
留意:經由測試,從nib文件加載的controller,只需不釋放,在每次viewWillAppare時都邑挪用layoutSubviews辦法,有時乃至會在viewDidAppare後在挪用一次layoutSubviews,而重點是從代碼加載的則只會在開端挪用一次,以後都不會,所以留意,在layoutSubviews中寫相干的結構代碼非常風險。
3、從storyBoard加載UIViewController實例的傳值圈套
我們曉得,當我們從StoryBoard中加載ViewController時,我們在Controller中拖拽的視圖是可以被初始化的,這外面有一點須要我們留意,假如我們須要向controller中視圖停止傳值設置,經由過程以下辦法獲得的Controller中,視圖還沒有被初始化創立出來:
ViewController2 * viewController2 = [[UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:@"ViewController2"];
我們可以在ViewController2的storyBoard中拉一個label,然後聯系關系到頭文件中,以下打印,會發明我們獲得controller時,外面的視圖對象並沒有停止創立:
ViewController2 * viewController2 = [[UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:@"ViewController2"];
打印以下:
NSLog(@"%@",viewController2.label);
[self presentViewController:viewController2 animated:YES completion:nil];
可以想象,假如我們這時候候須要對label停止一些屬性設置,必定掉敗。有人提出可以在創立後,手動調以下loadView辦法,我們試一下,成果以下:
可以看到,手動挪用loadView後,label是被創立了出來,然則暴漏了一個更嚴重的成績,體系不在挪用ViewDidLoad辦法,這是非常有風險的,由於我們年夜部門的初始化代碼都邑放在這個辦法裡,所以手動挪用loadView是一種毛病的辦法,apple文檔聲明關於loadView辦法,我們歷來都不要手動直接挪用,那末我們若何完成創立後對成員對象停止傳值設置呢,IOS9中增長了如許一個辦法:
- (void)loadViewIfNeeded NS_AVAILABLE_IOS(9_0);
這個辦法非常有效,挪用這個辦法,會將視圖創立出來,而且不會疏忽viewDidLoad的挪用。
在iOS9中,UIViewController還增長了上面一個布爾值的屬性,可以同來斷定controller的view能否曾經加載完成:
@property(nullable, nonatomic, readonly, strong) UIView *viewIfLoaded NS_AVAILABLE_IOS(9_0);
4、UIViewController與StroyBoard的相干互相辦法
關於ViewConroller,我們普通有兩種方法創立,一種是用純代碼的方法,一種是與StoryBoard聯系關系,在UIViewController中,有很多辦法便利我們與StoryBoard停止交互接洽。
1、ViewController直接在StoryBoard中停止跳轉的傳值
在StoryBoard中停止界面跳轉是非常便利的,我們在StoryBoard中拉入兩個ViewController,在一個下面添加一個按鈕,點住按鈕按住control,將鼠標拉到第二個controller上,會湧現以下的跳轉選項:
我們選擇一個後,就會在兩個controller之間樹立一個跳轉銜接。當我們運轉點擊按鈕後,會主動從第一個controller跳轉到第二個controller。在UIViewController中有以下辦法可以對能否跳轉停止掌握:
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(nullable id)sender NS_AVAILABLE_IOS(6_0);
這個辦法假如前往NO,主動跳轉將不克不及停止,會被謝絕,須要留意的是,這個辦法只會在主動的跳轉時被挪用,我們手動應用代碼跳轉StoryBoard中的銜接關系時是不會被挪用的,我們前面評論辯論。
在履行過上述辦法後,假如前往YES,體系還會在履行以下一個辦法,作為跳轉前的預備,我們可以在這個辦法中停止一些傳值操作,這個辦法不管使我們手動停止跳轉照樣storyboard中主動跳轉,都邑被履行:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(nullable id)sender NS_AVAILABLE_IOS(5_0);
sugur對象中封裝了相干的ViewController,可使用segue.destinationViewController獲得。
segue在StoryBoard中除用來主動正向跳轉外,我們還可以停止反向的跳轉,相似pop和dismiss辦法,這類segue被稱為unWind sugue。例如,我們有一個controller1和一個controllert2,要應用unWind segue從2前往1,我們須要在2中完成以下格局的辦法:
- (IBAction)unWindSegueToViewController:(UIStoryboardSegue *)segue {
這個辦法中的前往值必需為IBAction,參數必需是UIStoryboardSegue,辦法名我們可以本身界說,以後在StoryBoard中的ViewController1中的Exit選項中,我們會發明多了一個如許的辦法:
NSLog(@"unwindSegueToViewController");
}
我們可以把它銜接到viewController2中的一個按鈕上:
如許,當我們點擊viewController2中的按鈕時,就會前往到我們第一個ViewController1中了。
固然,在應用unwind segue辦法時,也是會有一些回調贊助我們停止跳轉前的設置和傳值,UIViewController以下辦法會在跳轉前挪用,前往NO,則不克不及停止跳轉:
-(BOOL)canPerformUnwindSegueAction:(SEL)action fromViewController:(UIViewController *)fromViewController withSender:(id)sender{
以後會履行我們自界說的unwindSegue辦法,這個辦法中我們可以甚麼都不寫,形式是會停止跳轉的。
NSLog(@"canPerformUnwindSegueAction");
return YES;
}
2、應用代碼跳轉Storyboard中的controller
我們除在Storyboard中拉拉扯扯可以停止掌握器的跳轉外,我們也能夠應用代碼來跳轉Storyboard中segue銜接關系。
在Storyboard中兩個掌握器間樹立一個segue接洽,我們可以取一個名字:
在觸發跳轉的辦法中,應用以下辦法停止跳轉,這外面的參數id就是我們獲得segue的id:
- (void)performSegueWithIdentifier:(NSString *)identifier sender:(nullable id)sender NS_AVAILABLE_IOS(5_0);
上面三個屬性我們可以獲得controller的nib文件名,其storyBoard和其Bundle:
@property(nullable, nonatomic, readonly, copy) NSString *nibName;
@property(nullable, nonatomic, readonly, strong) NSBundle *nibBundle;
@property(nullable, nonatomic, readonly, strong) UIStoryboard *storyboard NS_AVAILABLE_IOS(5_0);
5、UIViewController之間的一些附屬關系
這部門的內容和辦法能夠我們接觸用到的其實不多,然則在某些情形下,應用這些辦法可以年夜年夜的便利某些邏輯。
1、parentViewController
UIViewController外面封裝了一個數組,可以寄存其子ViewController,體系中應用的例子就是導航和tabBar這類的掌握器,我們應用以下辦法可以直接拜訪這些父的controller:
@property(nullable,nonatomic,weak,readonly) UIViewController *parentViewController;
2、模態跳轉中Controller的附屬
在我們停止掌握器的跳轉時,只需掌握器沒有被釋放,我們都可以順籐摸瓜的找到它,應用以下兩個辦法:
//其所present的contller,好比,A和B兩個controller,A跳轉到B,那末A的presentedViewController就是B
懂得了下面辦法我們可以曉得,關於反向傳值如許的成績,我們基本不須要署理,block,告訴等如許的龐雜手腕,只須要獲得跳轉到它的Controller,直接設置便可。舉個例子,我們須要在第二個界面消逝後,轉變第一個界面的色彩,在第二個controller中只須要上面的代碼便可完成 :
@property(nullable, nonatomic,readonly) UIViewController *presentedViewController NS_AVAILABLE_IOS(5_0);
//和下面的辦法恰好相反,好比,A和B兩個controller,A跳轉到B,那末B的presentingViewController就是A
@property(nullable, nonatomic,readonly) UIViewController *presentingViewController NS_AVAILABLE_IOS(5_0);
self.presentingViewController.view.backgroundColor = [UIColor colorWithRed:arc4random()%255/255.0 green:arc4random()%255/255.0 blue:arc4random()%255/255.0 alpha:1];
[self dismissViewControllerAnimated:YES completion:nil];
6、UIViewController的模態跳轉及動畫殊效
純真的UIViewController中,我們應用最多的是以下的兩個辦法,一個向前跳轉,一個向後前往:
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^ __nullable)(void))completion NS_AVAILABLE_IOS(5_0);
從辦法中,我們可以看到,有animated這個參數,來選擇能否有動畫殊效,默許的動畫殊效是像抽屜一樣從手機屏幕的下偏向上彈起,固然,這個後果我們可以停止設置,UIViewController有以下一個屬性來設置動畫殊效:
- (void)dismissViewControllerAnimated: (BOOL)flag completion: (void (^ __nullable)(void))completion NS_AVAILABLE_IOS(5_0);
@property(nonatomic,assign) UIModalTransitionStyle modalTransitionStyle NS_AVAILABLE_IOS(3_0);
留意,這個要設置的是將要跳轉到的controller,列舉以下:
typedef NS_ENUM(NSInteger, UIModalTransitionStyle) {
除跳轉的後果,還有一個屬性可以設置彈出的controler的填充後果,然則這個屬性只在pad上有用,在iphone上有效,都是填充到全部屏幕:
UIModalTransitionStyleCoverVertical = 0,//默許的,從下向上籠罩
UIModalTransitionStyleFlipHorizontal ,//程度翻轉
UIModalTransitionStyleCrossDissolve,//消融
UIModalTransitionStylePartialCurl ,從下向上翻頁
};
@property(nonatomic,assign) UIModalPresentationStyle modalPresentationStyle NS_AVAILABLE_IOS(3_2);
//列舉以下
typedef NS_ENUM(NSInteger, UIModalPresentationStyle) {
UIModalPresentationFullScreen = 0,//填充全部屏幕
UIModalPresentationPageSheet,//留下狀況欄
UIModalPresentationFormSheet,//周圍留下變暗的空白
UIModalPresentationCurrentContext ,//和跳轉到它的掌握器堅持分歧
UIModalPresentationCustom NS_ENUM_AVAILABLE_IOS(7_0),//自界說
UIModalPresentationOverFullScreen NS_ENUM_AVAILABLE_IOS(8_0),
UIModalPresentationOverCurrentContext NS_ENUM_AVAILABLE_IOS(8_0),
UIModalPresentationPopover NS_ENUM_AVAILABLE_IOS(8_0) __TVOS_PROHIBITED,
UIModalPresentationNone NS_ENUM_AVAILABLE_IOS(7_0) = -1,
};
7、viewController顯示(封閉)其它viewController
在5.0之前,對應的辦法是應用model view controller系列的辦法。5.0今後增長了presented,prensentingViewController的概念,modalViewController對應5.0後的presentedViewController
FCDemoViewController *controller= [[FCDemoViewController alloc]initWithNibName:@"FCDemoViewController" bundle:nil];
屬性modalPresentationStyle在iPad下有幾種顯示情勢,對應分歧的顯示區域。屬性modellTransitionStyle決議過渡情勢.
controller.modalTransitionStyle=UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];
NSLog(@"%@",self.modalViewController);
//5.0
[self presentViewController:controller animated:YES completion:nil];
NSLog(@"%@",self.presentedViewController);
NSLog(@"%@",self.presentingViewController);
封閉也有對應的辦法:dismissModalViewControllerAnimated或iOS5.0今後的dismissViewControllerAnimated:completion:
5.0今後其它的變更:
controller可以自界說子controller的聚集,如許每個controller都可所以一個container controller.
definesPresentationContext決議以後顯示其它controller的controller能否供給context給presentedViewController(modalViewController),假如不,就會找上一級的controller的該值。
具體的操作可以檢查class reference.
蘋果官方推舉應用協定的方法來讓controller互相通訊。起首聲明一個協定,並在主controller中完成該協定的辦法,在顯示其它controller的時刻,為其設置delegate=self.如許在其它controller須要回調presentingViewController便可以直接用delegate辦法往返調到它。經由過程如許的方法,可使得復用性年夜年夜加強。並且被顯示的controller也不消完整曉得顯示它的controller的一切信息和屬性。
【iOS App開辟中UIViewController類的應用教程】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!