亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

iOS App開發中UIViewController類的使用教程

2020-07-26 03:18:19
字體:
來源:轉載
供稿:網友

一、引言
作為MVC設計模式中的C,Controller一直扮演著項目開發中最重要的角色,它是視圖和數據的橋梁,通過它的管理,將數據有條有理的展示在我們的View層上。iOS中的UIViewController是UIKit框架中最基本的一個類。從第一個UI視圖到復雜完整項目,都離不開UIViewController作為基礎?;赨IViewController的封裝和擴展,也能夠出色的完成各種復雜界面邏輯。這里旨在討論UIViewController的生命周期和屬性方法,在最基礎的東西上,往往會得到意想不到的驚喜。

二、UIViewController的生命周期
要了解UIViewController,先要弄清楚其生命周期。在面向對象的語言中,是對象,就一定要有生命周期,UIViewController也不例外,生命周期管理Controller的作用范圍和時間,也管理其內對象的作用范圍和時間。首先,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;
上面這么多的函數,乍一看什么復雜,其實關系什么明朗,除了initialize,init和initWithCoder不是存在所有對象的聲明周期中,其他函數都會在UIViewController的聲明周期中有序的被調用。那么具體的調用順序是怎樣的呢,最好的辦法是實踐一下,通過編號打印,結果如下:

201671392151482.png (491×140)

這是一個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中寫相關的布局代碼十分危險。

三、從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];
打印如下:

201671392253365.png (492×140)

可以想象,如果我們這時候需要對label進行一些屬性設置,必然失敗。有人提出可以在創建后,手動調以下loadView方法,我們試一下,結果如下:

201671392309060.png (522×141)

可以看到,手動調用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);

 

四、UIViewController與StroyBoard的相關相互方法
對于ViewConroller,我們一般有兩種方式創建,一種是用純代碼的方式,一種是與StoryBoard關聯,在UIViewController中,有許多方法方便我們與StoryBoard進行交互聯系。
1、ViewController直接在StoryBoard中進行跳轉的傳值
在StoryBoard中進行界面跳轉是十分方便的,我們在StoryBoard中拉入兩個ViewController,在一個上面添加一個按鈕,點住按鈕按住control,將鼠標拉到第二個controller上,會出現如下的跳轉選項:

201671392354982.png (192×84)

我們選擇一個后,就會在兩個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 {
    NSLog(@"unwindSegueToViewController");
}
這個方法中的返回值必須為IBAction,參數必須是UIStoryboardSegue,方法名我們可以自己定義,之后在StoryBoard中的ViewController1中的Exit選項中,我們會發現多了一個這樣的方法:

201671392429121.png (368×135)

我們可以把它連接到viewController2中的一個按鈕上:

201671392452838.png (363×336)

這樣,當我們點擊viewController2中的按鈕時,就會返回到我們第一個ViewController1中了。
當然,在使用unwind segue方法時,也是會有一些回調幫助我們進行跳轉前的設置和傳值,UIViewController如下方法會在跳轉前調用,返回NO,則不能進行跳轉:
-(BOOL)canPerformUnwindSegueAction:(SEL)action fromViewController:(UIViewController *)fromViewController withSender:(id)sender{
    NSLog(@"canPerformUnwindSegueAction");
    return YES;
}
之后會執行我們自定義的unwindSegue方法,這個方法中我們可以什么都不寫,模式是會進行跳轉的。
2、使用代碼跳轉Storyboard中的controller
我們除了在Storyboard中拉拉扯扯可以進行控制器的跳轉外,我們也可以使用代碼來跳轉Storyboard中segue連接關系。
在Storyboard中兩個控制器間建立一個segue聯系,我們可以取一個名字:

201671392533287.png (248×176)

在觸發跳轉的方法中,使用如下方法進行跳轉,這里面的參數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);

 

五、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
@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);
了解了上面方法我們可以知道,對于反向傳值這樣的問題,我們根本不需要代理,block,通知等這樣的復雜手段,只需要獲取跳轉到它的Controller,直接設置即可。舉個例子,我們需要在第二個界面消失后,改變第一個界面的顏色,在第二個controller中只需要下面的代碼即可實現 :
    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];

六、UIViewController的模態跳轉及動畫特效
單純的UIViewController中,我們使用最多的是如下的兩個方法,一個向前跳轉,一個向后返回:
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^ __nullable)(void))completion NS_AVAILABLE_IOS(5_0);
- (void)dismissViewControllerAnimated: (BOOL)flag completion: (void (^ __nullable)(void))completion NS_AVAILABLE_IOS(5_0);
從方法中,我們可以看到,有animated這個參數,來選擇是否有動畫特效,默認的動畫特效是像抽屜一樣從手機屏幕的下方向上彈起,當然,這個效果我們可以進行設置,UIViewController有如下一個屬性來設置動畫特效:
@property(nonatomic,assign) UIModalTransitionStyle modalTransitionStyle NS_AVAILABLE_IOS(3_0);
注意,這個要設置的是將要跳轉到的controller,枚舉如下:
typedef NS_ENUM(NSInteger, UIModalTransitionStyle) {
    UIModalTransitionStyleCoverVertical = 0,//默認的,從下向上覆蓋
    UIModalTransitionStyleFlipHorizontal ,//水平翻轉
    UIModalTransitionStyleCrossDissolve,//溶解
    UIModalTransitionStylePartialCurl ,從下向上翻頁
};
除了跳轉的效果,還有一個屬性可以設置彈出的controler的填充效果,但是這個屬性只在pad上有效,在iphone上無效,都是填充到整個屏幕:
@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,        
};

七、viewController顯示(關閉)其它viewController
在5.0之前,對應的方法是使用model view controller系列的方法。5.0以后增加了presented,prensentingViewController的概念,modalViewController對應5.0后的presentedViewController

FCDemoViewController *controller= [[FCDemoViewController alloc]initWithNibName:@"FCDemoViewController" bundle:nil]; 
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);  
 屬性modalPresentationStyle在iPad下有幾種顯示形式,對應不同的顯示區域。屬性modellTransitionStyle決定過渡形式.
關閉也有對應的方法: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的所有信息和屬性。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲国产精品久久久久| 欧美日韩电影在线观看| 亚洲第一偷拍网| 伊人久久久久久久久久久久久| 亚洲电影天堂av| 亚洲一区二区日本| 国产精品偷伦免费视频观看的| 欧日韩不卡在线视频| 国模gogo一区二区大胆私拍| 欧美一区二区.| 日本亚洲欧洲色α| 久久久亚洲网站| 亚洲欧洲自拍偷拍| 欧美日在线观看| 深夜福利亚洲导航| 国产午夜精品理论片a级探花| 欧美激情三级免费| 国产日韩亚洲欧美| 国产欧美在线视频| 91久久国产综合久久91精品网站| 91中文字幕在线观看| 91久久精品国产| 国产日韩欧美夫妻视频在线观看| 国产美女久久精品香蕉69| 欧美日韩福利视频| 成人欧美一区二区三区黑人孕妇| 色综合亚洲精品激情狠狠| 久久免费福利视频| 在线成人中文字幕| 国产欧美最新羞羞视频在线观看| 国产精品久久久久免费a∨大胸| 亚洲成人精品久久久| 国产精品视频永久免费播放| 成人精品在线视频| 亚洲free嫩bbb| 91网站免费观看| 精品福利免费观看| 欧美交受高潮1| 亚洲综合小说区| 久久亚洲精品国产亚洲老地址| 亚洲天堂男人的天堂| 亚洲丝袜一区在线| 成人黄色免费在线观看| 日韩欧美国产网站| 久久久中文字幕| 日韩欧美中文字幕在线观看| 亚洲精美色品网站| 国产一区二区三区丝袜| 亚洲欧美在线第一页| 亚洲电影第1页| 亚洲免费小视频| 国产在线视频欧美| 日本精品一区二区三区在线播放视频| 91精品国产自产在线老师啪| 国产欧美在线视频| 国产精品久久久久久久app| 亚洲乱亚洲乱妇无码| 成人黄色av播放免费| 亚州国产精品久久久| 成人激情免费在线| 久操成人在线视频| 成人欧美一区二区三区在线湿哒哒| 日韩欧美精品在线观看| 欧美亚洲在线视频| 亚洲最大的免费| 奇米四色中文综合久久| 国产日韩精品综合网站| 国产在线观看91精品一区| 热re91久久精品国99热蜜臀| 久久久亚洲网站| 亚洲综合自拍一区| 日韩美女av在线免费观看| 日韩欧美国产一区二区| 51色欧美片视频在线观看| 97国产真实伦对白精彩视频8| 91精品啪在线观看麻豆免费| 少妇精69xxtheporn| 亚洲国模精品私拍| 久久精品国产一区二区三区| 欧美性xxxxxxx| 最好看的2019的中文字幕视频| 亚洲激情视频网站| 久久久91精品国产| 久久久久久久一区二区| 亚洲欧美中文字幕在线一区| 欧美激情中文字幕在线| 国产精品成人观看视频国产奇米| 日日骚av一区| 欧美日韩一二三四五区| 国产精品免费久久久久影院| 国产精品影片在线观看| 国语自产偷拍精品视频偷| 精品国产视频在线| 91探花福利精品国产自产在线| 97涩涩爰在线观看亚洲| 成人欧美一区二区三区黑人孕妇| 在线精品视频视频中文字幕| 久久777国产线看观看精品| 亚洲新中文字幕| 亚洲色在线视频| 国产日韩综合一区二区性色av| 国产免费一区二区三区香蕉精| 2019精品视频| 精品久久久久久中文字幕一区奶水| 九九视频直播综合网| 俺也去精品视频在线观看| 日韩中文字幕免费视频| 精品国产鲁一鲁一区二区张丽| 中文字幕在线观看日韩| 精品视频在线播放| 国产精欧美一区二区三区| 日本精品免费一区二区三区| 国模吧一区二区三区| 国产综合在线观看视频| 91av在线精品| 欧美精品午夜视频| 亚洲国产精品国自产拍av秋霞| 日本久久久久久| www欧美日韩| 色阁综合伊人av| 国产一区在线播放| 国产精品私拍pans大尺度在线| 国产精品视频区| 国产噜噜噜噜噜久久久久久久久| 亚洲精品一区二区三区不| 国产成人aa精品一区在线播放| 欧美成人精品在线视频| 国产精品久久国产精品99gif| 国产日韩欧美一二三区| 久久久久www| 亚洲自拍偷拍色片视频| 在线午夜精品自拍| 性欧美长视频免费观看不卡| 一区二区国产精品视频| 日日噜噜噜夜夜爽亚洲精品| 亚洲国产女人aaa毛片在线| 欧洲亚洲妇女av| 姬川优奈aav一区二区| 日韩免费av在线| 午夜精品久久久久久久99黑人| 亚洲精品小视频在线观看| 97精品在线观看| 97色在线观看| 欧美成人小视频| 丝袜美腿精品国产二区| 成人亚洲欧美一区二区三区| 亚洲一区亚洲二区亚洲三区| 国产亚洲视频中文字幕视频| 4p变态网欧美系列| 欧美老妇交乱视频| 国产日韩欧美黄色| 亚洲四色影视在线观看| 亚洲香蕉av在线一区二区三区| 国产亚洲精品久久| 97在线免费视频| 国产一区二区三区精品久久久| 国产日韩在线亚洲字幕中文| 亚洲性猛交xxxxwww| 久久久在线视频| 欧美限制级电影在线观看| 美女久久久久久久久久久| 隔壁老王国产在线精品| 国产精品久久久久久久久久久久久| 国产精品久久久久国产a级|