
目錄
-
UIViewController
- 職責(zé)
- 視圖管理
- 處理與視圖相關(guān)的通知
- 實(shí)現(xiàn)容器視圖控制器
- 內(nèi)存管理
- 生命周期
-
以代碼的方式創(chuàng)建一個(gè)控制器
- initWithNibName:bundle:
- initWithCoder:
-
管理視圖
- view
- viewLoaded
- loadView
- viewDidLoad
- loadViewIfNeeded
- viewIfLoaded
- title
- preferredContentSize
-
呈現(xiàn)視圖控制器
- modalPresentationStyle
- modalTransitionStyle
- showViewController:sender:
- presentViewController:animated:completion:
- dismissViewControllerAnimated:completion:
-
響應(yīng)View事件
- View XX Appear
- beingDismissed && beingPresented
- Moving XX ParentViewController
-
安全區(qū)域
- additionalSafeAreaInsets
- viewSafeAreaInsetsDidChange
-
布局視圖
- edgesForExtendedLayout
- extendedLayoutIncludesOpaqueBars
- updateViewConstraints
- viewWill/DidLayoutSubviews
-
子視圖控制器
- childViewControllers
- addChildViewController:
- removeFromParentViewController
- transitionFromViewController:toViewController:duration:options:animations:completion:
- shouldAutomaticallyForwardAppearanceMethods
- AppearanceTransition
- 響應(yīng)容器事件
- willMoveToParentViewController
- didMoveToParentViewController
-
獲取其他控制器
- presentingViewController && presentedViewController
- parentViewController
- navigationController
- splitViewController
- tabBarController
- 處理內(nèi)存警告
- didReceiveMemoryWarning
-
協(xié)調(diào)系統(tǒng)手勢
- preferredScreenEdgesDeferringSystemGestures
- childViewControllerForScreenEdgesDeferringSystemGestures
-
管理狀態(tài)欄
- childViewControllerForStatusBarStyle
- childViewControllerForStatusBarHidden
- preferredStatusBarStyle
- prefersStatusBarHidden
- modalPresentationCapturesStatusBarAppearance
- preferredStatusBarUpdateAnimation
- setNeedsStatusBarAppearanceUpdate
-
配置導(dǎo)航入口
- navigationItem
- hidesBottomBarWhenPushed
- toolbarItems
- tabBarItem
- 編輯行為
- editing
- setEditing:animated:
- editButtonItem
UIViewController
-
職責(zé)
- 更新視圖內(nèi)容
- 響應(yīng)交互
- 調(diào)整入口View布
- 與程序中其他對(duì)象(包括其他控制器)進(jìn)行協(xié)調(diào)
UIViewController作為UIResponder、被插入響應(yīng)鏈之間。如果其持有的視圖中沒有一個(gè)可以處理某事件、控制器可以選擇自行處理或者傳遞給父視圖。
控制器很少單獨(dú)被使用、我們通常使用多個(gè)控制器進(jìn)行相互的跳轉(zhuǎn)作業(yè)。
-
視圖管理
根View主要充當(dāng)視圖層次結(jié)構(gòu)的其余部分的容器。
根View的大小和位置由擁有它的對(duì)象決定,該對(duì)象要么是視圖控制器,要么是應(yīng)用程序的Window。
Window所擁有的視圖控制器是應(yīng)用程序的根View控制器,它的視圖是用來填充Window的。
View屬性是懶加載的、有幾種方式可以指定ViewController的View:
- Storyboard
可以指定視圖及其與視圖控制器的連接。
你也指定視圖控制器之間的關(guān)系和segue。 - Nib
使用Nib文件為視圖控制器指定單個(gè)視圖控制器的視圖。
但不允許定義segue或視圖控制器之間的關(guān)系。 - loadView方法
以代碼方式創(chuàng)建視圖層次結(jié)構(gòu),并將該層次結(jié)構(gòu)的根視圖分配給視圖控制器的View屬性。
所有的方式都能導(dǎo)向相同的結(jié)果:創(chuàng)建VIew并且通過ViewController.view屬性進(jìn)行公開。
需要注意的是
多個(gè)Controller使用同一個(gè)Storyboard或者Nib作為View屬性時(shí)、他們會(huì)持有單獨(dú)的副本。
而代碼方式、你必須確保View不會(huì)被多個(gè)VC持有。
-
處理與視圖相關(guān)的通知
視圖的可見性
當(dāng)視圖的可見性發(fā)生變化時(shí),視圖控制器會(huì)自動(dòng)調(diào)用它自己的方法,以便子類可以對(duì)變化做出響應(yīng)。比如viewWillAppear在展示之前進(jìn)行設(shè)置、viewWillDisappear:在消失之前進(jìn)行狀態(tài)保存或更改。

-
實(shí)現(xiàn)容器視圖控制器
我們的日常開發(fā)中常有這樣一種需求,通過切換標(biāo)簽來切換不同的頁面,如果在一個(gè) controller 管理這些 view 的話,代碼就顯得耦合度過高,也與 Apple 的 MVC 模式不符合,Apple 推薦一個(gè) controller 管理一個(gè) view。這樣做有三個(gè)好處:
1.無疑,對(duì)頁面中的邏輯更加分明了。相應(yīng)的View對(duì)應(yīng)相應(yīng)的ViewController。
2.當(dāng)某個(gè)子View沒有顯示時(shí),將不會(huì)被Load,減少了內(nèi)存的使用。
3.當(dāng)內(nèi)存緊張時(shí),沒有Load的View將被首先釋放,優(yōu)化了程序的內(nèi)存釋放機(jī)制。
4.在子VC上調(diào)用self.navigationController可以傳遞給父VC。(UIPageController上特別好用)
像這樣使用
//添加
[self addChildViewController:sfViewControllr];
[self.view addSubview:sfViewControllr.view];
sfViewControllr.view.frame = CGRectMake(0, 300, 1, 1);
//移除
[sfViewControllr didMoveToParentViewController:self];
如果只是 [self.view addSubview:sfViewControllr.view]; 的方式用另一個(gè) controller 來控制,但是這樣會(huì)產(chǎn)生一個(gè)新的問題:直接 add 進(jìn)去的subView不在 viewController的 view hierarchy 內(nèi),事件不會(huì)正常傳遞,如:旋轉(zhuǎn)、觸摸等,屬于危險(xiǎn)操作違背CocoaTouch開發(fā)的設(shè)計(jì)MVC原則,viewController應(yīng)該且只應(yīng)該管理一個(gè)view hierarchy。
-
內(nèi)存管理
內(nèi)存是iOS中的關(guān)鍵資源,視圖控制器提供了內(nèi)置支持,在關(guān)鍵時(shí)刻減少內(nèi)存占用。UIViewController類通過它的didReceiveMemoryWarning方法提供一些低內(nèi)存條件的自動(dòng)處理,這些方法釋放不需要的內(nèi)存。
-
生命周期
- +[ViewController load]
- +[ViewController initialize]
- -[ViewController init]
- -[ViewController loadView]
- -[ViewController viewDidLoad]
- -[ViewController viewWillAppear:]
- -[ViewController updateViewConstraints]
- -[ViewController viewWillLayoutSubviews]
- -[ViewController viewDidLayoutSubviews]
- -[ViewController viewDidAppear:]
- -[ViewController dealloc]
其中1和2嚴(yán)格意義上來講應(yīng)該不算在內(nèi)
以代碼的方式創(chuàng)建一個(gè)控制器
-
- initWithNibName:bundle:
通過代碼的方式實(shí)例化一個(gè)IB方式創(chuàng)建的控制器
- (instancetype)initWithNibName:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil;
TestViewController *tvc = [[TestViewController alloc] initWithNibName:@"xx" bundle:nil]; // 注意xib名字不要后綴
需要指定xx.xib的file’s owner的Custom Class為TestViewController,并且把file’s owner的view指定為其中的一個(gè)view
-
- initWithCoder:
在IB中創(chuàng)建的類、但在xocde中被實(shí)例化時(shí)被調(diào)用
- (instancetype)initWithCoder:(NSCoder *)aDecoder;
管理視圖
-
view
容器視圖
@property(nonatomic, strong) UIView *view;
- 這個(gè)屬性是來加載的、當(dāng)你訪問時(shí)如果為nil、將調(diào)用
loadView方法并返回view。 - 每一個(gè)VC、都必須是該View的唯一一個(gè)持有者。(例外情況是通過
addChildViewController:方法添加后、將vc.view add給另一個(gè)vc) - 你可以通過
isViewLoaded方法來檢測當(dāng)前vc是否已經(jīng)持有視圖。(這樣不會(huì)觸發(fā)懶加載)。 - VC有權(quán)在低內(nèi)存情況下以及VC最終釋放時(shí)、釋放這個(gè)屬性。
-
viewLoaded
self.view是否有值
@property(nonatomic, readonly, getter=isViewLoaded) BOOL viewLoaded;
這個(gè)屬性的檢測不會(huì)觸發(fā)view屬性的懶加載。
-
- loadView
創(chuàng)建容器視圖
- (void)loadView;
當(dāng)view屬性被訪問但本身沒有值時(shí)觸發(fā)、你可以在這里自定義view屬性的視圖。
- 永遠(yuǎn)不要直接調(diào)用這個(gè)方法。
- 如果使用
nib、該方法從nib中加載視圖。如果不是、則直接創(chuàng)建一個(gè)UIView。 - 如果使用IB來創(chuàng)建VC、不要覆蓋這個(gè)方法。
- 如果自定義
view。您創(chuàng)建的視圖應(yīng)該是唯一的實(shí)例,不應(yīng)該與任何其他視圖控制器對(duì)象共享。此方法的自定義實(shí)現(xiàn)不應(yīng)調(diào)用super。 - 如果想對(duì)
view進(jìn)行其余的動(dòng)作(添加subVIew等等)、請(qǐng)?jiān)?/code>viewDidLoad`中執(zhí)行。
通常用在進(jìn)到vc就要切換view的時(shí)候使用、比如進(jìn)來就是一張圖片啊、webView啊之類。
-
- viewDidLoad
在
loadView后執(zhí)行。表示此時(shí)已經(jīng)有view屬性
- (void)viewDidLoad;
不管視圖層次結(jié)構(gòu)是從nib文件加載的還是在loadView方法中以編程方式創(chuàng)建的,都會(huì)調(diào)用此方法。
通常在這里對(duì)view進(jìn)行進(jìn)一步配置。
-
loadViewIfNeeded
主動(dòng)嘗試調(diào)用loadView
- (void)loadViewIfNeeded;
正常如果我們主動(dòng)調(diào)用[self loadView];是不會(huì)觸發(fā)viewDidLoad的、但這個(gè)方法可以。
不過似乎必須要[self isViewLoaded] == NO才行
-
viewIfLoaded
返回vc的view。并且不會(huì)觸發(fā)懶加載
@property(nonatomic, readonly, strong) UIView *viewIfLoaded;
如果沒有則返回nil
-
title
標(biāo)題
@property(nonatomic, copy) NSString *title;
如果VC有一個(gè)有效的導(dǎo)航項(xiàng)或標(biāo)簽欄項(xiàng),為該屬性賦值將更新這些對(duì)象的標(biāo)題文本。
相當(dāng)于同時(shí)設(shè)置了tabBarItem.title和navigationItem.title。
-
preferredContentSize
我們可以使用preferredContentSize來設(shè)置我們期望的childViewController的界面的大小
@property(nonatomic) CGSize preferredContentSize;
沒太理解怎么用、有明白的大佬舉個(gè)例子?
似乎在ipad上有用
呈現(xiàn)視圖控制器
-
modalPresentationStyle
模態(tài)跳轉(zhuǎn)的樣式
@property(nonatomic, assign) UIModalPresentationStyle modalPresentationStyle;
UIModalPresentationStyle為一個(gè)枚舉類型
在iPhone和iPod touch上面系統(tǒng)始終已UIModalPresentationFullScreen模式顯示presented VC。(哈哈哈。很氣、我試了半天差了好多資料最后看到這句話)
typedefNS_ENUM(NSInteger, UIModalPresentationStyle) {
UIModalPresentationFullScreen =0,//全屏覆蓋
UIModalPresentationPageSheet,//彈出VC時(shí),presented VC的高度和當(dāng)前屏幕高度相同,寬度和豎屏模式下屏幕寬度相同,剩余未覆蓋區(qū)域?qū)?huì)變暗并阻止用戶點(diǎn)擊,這種彈出模式下,豎屏?xí)r跟 UIModalPresentationFullScreen的效果一樣,橫屏?xí)r候兩邊則會(huì)留下變暗的區(qū)域。
UIModalPresentationFormSheet,// presented VC的高度和寬度均會(huì)小于屏幕尺寸,presented VC居中顯示,四周留下變暗區(qū)域。
UIModalPresentationCurrentContext,//這種模式下,presented VC的彈出方式和presenting VC的父VC的方式相同。
UIModalPresentationCustom,//自定義視圖展示風(fēng)格,由一個(gè)自定義演示控制器和一個(gè)或多個(gè)自定義動(dòng)畫對(duì)象組成。符合UIViewControllerTransitioningDelegate協(xié)議。使用視圖控制器的transitioningDelegate設(shè)定您的自定義轉(zhuǎn)換。
UIModalPresentationOverFullScreen,//如果視圖沒有被填滿,底層視圖可以透過
UIModalPresentationOverCurrentContext,//視圖全部被透過
UIModalPresentationPopover,
UIModalPresentationNone ,
};
-
modalTransitionStyle
設(shè)置過渡動(dòng)畫樣式
@property(nonatomic, assign) UIModalTransitionStyle modalTransitionStyle;
在通過presentViewController:animated:completion:進(jìn)行模態(tài)跳轉(zhuǎn)時(shí)的專場動(dòng)畫樣式。默認(rèn)UIModalTransitionStyleCoverVertical
UIModalTransitionStyle是一個(gè)枚舉類型
typedef NS_ENUM(NSInteger, UIModalTransitionStyle) {
UIModalTransitionStyleCoverVertical =0,//從底部滑入
UIModalTransitionStyleFlipHorizontal,//水平翻轉(zhuǎn)
UIModalTransitionStyleCrossDissolve,//交叉溶解
UIModalTransitionStylePartialCurl NS_ENUM_AVAILABLE_IOS(3_2),//翻頁效果
};
-
showViewController:sender:
大一統(tǒng)的跳轉(zhuǎn)方法
- (void)showViewController:(UIViewController *)vc
sender:(id)sender;
- (void)showDetailViewController:(UIViewController *)vc
sender:(id)sender;
全能型界面切換的方法,它能根據(jù)當(dāng)前的試圖控制器情況來決定是用navVC的push方法還是普通VC的Modal方式來切換界面。
- 當(dāng)前界面是Nav的子VC時(shí)
它會(huì)用push方式切換。 - 當(dāng)前界面為Modal的界面,
就會(huì)用modal方式切換。
但也有些缺陷、比如不能設(shè)置是否執(zhí)行動(dòng)畫、獲取不到完成的block。
一般情況下,horizontally compact(iphone) 環(huán)境下,意義不大(因?yàn)椴惶枰紤]UISplitViewController)。
-
- presentViewController:animated:completion:
以模態(tài)方式呈現(xiàn)一個(gè)VC
- (void)presentViewController:(UIViewController *)viewControllerToPresent
animated:(BOOL)flag
completion:(void (^)(void))completion;
在水平規(guī)則環(huán)境中,視圖控制器以modalPresentationStyle屬性指定的樣式表示。
任何情況下都可以通過modalTransitionStyle屬性進(jìn)行轉(zhuǎn)場設(shè)置。
在viewDidAppear之后調(diào)用completion回調(diào)。
-
- dismissViewControllerAnimated:completion:
退出一個(gè)由模態(tài)方式展示的VC
- (void)dismissViewControllerAnimated:(BOOL)flag
completion:(void (^)(void))completion;
在viewDidDisappear之后調(diào)用completion回調(diào)。
響應(yīng)View事件
-
View XX Appear
視圖的顯示與隱藏
- (void)viewWillAppear:(BOOL)animated; // 視圖即將顯示時(shí)調(diào)用
- (void)viewDidAppear:(BOOL)animated; // 視圖已經(jīng)顯示時(shí)調(diào)用
- (void)viewWillDisappear:(BOOL)animated; // 視圖將要消失時(shí)調(diào)用
- (void)viewDidDisappear:(BOOL)animated; // 視圖已經(jīng)消失時(shí)調(diào)用
這張圖應(yīng)該很清楚了

.h文件里說這四個(gè)方法默認(rèn)什么都不做、但是文檔里說務(wù)必調(diào)用super方法。
-
beingDismissed && beingPresented
視圖是否正在消失/顯示
@property(nonatomic, readonly, getter=isBeingPresented) BOOL beingPresented NS_AVAILABLE_IOS(5_0); //正在顯示
@property(nonatomic, readonly, getter=isBeingDismissed) BOOL beingDismissed NS_AVAILABLE_IOS(5_0);//正在消失
-
Moving XX ParentViewController
視圖是否正在從父VC來/向父VC去
@property(nonatomic, readonly, getter=isMovingToParentViewController) BOOL movingToParentViewController NS_AVAILABLE_IOS(5_0); //向父VC去
@property(nonatomic, readonly, getter=isMovingFromParentViewController) BOOL movingFromParentViewController NS_AVAILABLE_IOS(5_0); //從父VC來
安全區(qū)域
-
additionalSafeAreaInsets
修改安全區(qū)域的內(nèi)嵌程度
@property(nonatomic) UIEdgeInsets additionalSafeAreaInsets;
比如如果SafeAreaInset值為(20,0,0,0),那么頁面上的TableVIew可能會(huì)下移20個(gè)單位。
此時(shí)設(shè)置additionalSafeAreaInsets屬性值為(-20,0,0,0),則SafeAreaInsets不會(huì)對(duì)adjustedContentInset值產(chǎn)生影響。以便正常顯示。
有興趣可以看看《iOS 11 安全區(qū)域適配總結(jié)》
-
- viewSafeAreaInsetsDidChange
當(dāng)VC的
safeAreaInsets發(fā)生改變是被調(diào)用
- (void)viewSafeAreaInsetsDidChange;
布局視圖
-
edgesForExtendedLayout
指定view的邊(上、下、左、右)延伸到整個(gè)屏幕
@property(nonatomic, assign) UIRectEdge edgesForExtendedLayout;
默認(rèn)值是UIRectEdgeAll, 意味著view會(huì)被拓展到整個(gè)屏幕。
它只有當(dāng)viewController被嵌到別的container view controller中時(shí)才會(huì)起作用
-
extendedLayoutIncludesOpaqueBars
如果status bar是不透明的,view不會(huì)被延伸到status bar,除非extendedLayoutIncludesOpaqueBars = YES;
@property(nonatomic, assign) BOOL extendedLayoutIncludesOpaqueBars;
默認(rèn)為NO。在iOS 7.0中,bars默認(rèn)是半透明的。
-
updateViewConstraints
當(dāng)自身view屬性的布局被修改時(shí)被自動(dòng)調(diào)用
- (void)updateViewConstraints;
這個(gè)方法默認(rèn)的實(shí)現(xiàn)是調(diào)用對(duì)應(yīng)View的 -updateConstraints
調(diào)用[super updateViewConstraints]作為實(shí)現(xiàn)的最后一步。
-
viewWill/DidLayoutSubviews
重新布局子View前/后調(diào)用
- (void)viewWillLayoutSubviews NS_AVAILABLE_IOS(5_0);
- (void)viewDidLayoutSubviews NS_AVAILABLE_IOS(5_0);
這兩個(gè)方法的默認(rèn)實(shí)現(xiàn)什么都不做
其中viewDidLayoutSubviews可以獲取子控件正確的frame
子視圖控制器
具體的作用可以回去看看《UIViewController》 >>>《實(shí)現(xiàn)容器視圖控制器》部分的解釋。
-
childViewControllers
存放子VC的數(shù)組
@property(nonatomic, readonly) NSArray<__kindof UIViewController *> *childViewControllers;
-
- addChildViewController:
添加子VC
- (void)addChildViewController:(UIViewController *)childController;
-
- removeFromParentViewController
從父VC上移除
- (void)removeFromParentViewController;
-
- transitionFromViewController:toViewController:duration:options:animations:completion:
通過動(dòng)畫的方式操作兩個(gè)子VC
- (void)transitionFromViewController:(UIViewController *)fromViewController
toViewController:(UIViewController *)toViewController
duration:(NSTimeInterval)duration
options:(UIViewAnimationOptions)options
animations:(void (^)(void))animations
completion:(void (^)(BOOL finished))completion;
《iOS 中使用ViewController控制轉(zhuǎn)場的各種方法》
-
shouldAutomaticallyForwardAppearanceMethods
是否將
appearance callbacks事件傳遞給子VC
@property(nonatomic, readonly) BOOL shouldAutomaticallyForwardAppearanceMethods;
appearance callbacks基本上指viewWillDisappear,viewDidDisappear之類方法。
默認(rèn)為YES、你可以重載以禁用
- (BOOL)shouldAutomaticallyForwardAppearanceMethods
{
return NO;
}
-
AppearanceTransition
調(diào)起指定的
appearance callbacks
- (void)beginAppearanceTransition:(BOOL)isAppearing
animated:(BOOL)animated;
- (void)endAppearanceTransition;
動(dòng)傳遞的時(shí)候你并不能直接去調(diào)用child的viewWillAppear或者viewDidAppear這些方法,而是需要使用 beginAppearanceTransition:animated:和endAppearanceTransition接口來間接觸發(fā)那些appearance callbacks
且begin和end必須成對(duì)出現(xiàn)。
[content beginAppearanceTransition:YES animated:animated]觸發(fā)content的viewWillAppear
[content beginAppearanceTransition:NO animated:animated]觸發(fā)content的viewWillDisappear,
和他們配套的[content endAppearanceTransition]分別觸發(fā)viewDidAppear和viewDidDisappear。
響應(yīng)容器事件
-
- willMoveToParentViewController
將要添加到容器VC時(shí)調(diào)用
- (void)willMoveToParentViewController:(UIViewController *)parent;
將BVC通過addChildViewController給A、接口建立了邏輯上的父子關(guān)系,BVC可以通過parentViewController,訪問AVC,addChildViewController:接口的邏輯中會(huì)自動(dòng)調(diào)用 [BVC willMoveToParentViewController:self];
-
didMoveToParentViewController
從容器VC上移除時(shí)調(diào)用
- (void)didMoveToParentViewController:(UIViewController *)parent;
同上、在調(diào)用removeFromParentViewController時(shí)內(nèi)部會(huì)調(diào)用[BVC didMoveToParentViewController:nil]
獲取其他控制器
-
presentingViewController && presentedViewController
presen別人的控制器、被presen的控制器
@property(nonatomic, readonly) UIViewController *presentingViewController;//來自
@property(nonatomic, readonly) UIViewController *presentedViewController;//去往
假設(shè)從A控制器通過present的方式跳轉(zhuǎn)到了B控制器,那么 A.presentedViewController 就是B控制器;B.presentingViewController 就是A控制器。
-
parentViewController
父VC
@property(nonatomic, weak, readonly) UIViewController *parentViewController;
-
navigationController
持有該VC的導(dǎo)航欄控制器
@property(nonatomic, readonly, strong) UINavigationController *navigationController;
-
splitViewController
持有該VC的分屏控制器
@property(nonatomic, readonly, strong) UISplitViewController *splitViewController;
-
tabBarController
持有該VC的tabBar控制器
@property(nonatomic, readonly, strong) UITabBarController *tabBarController;
處理內(nèi)存警告
-
didReceiveMemoryWarning
當(dāng)應(yīng)用程序收到內(nèi)存警告的時(shí)候會(huì)調(diào)用這個(gè)方法 ,做相應(yīng)的解決內(nèi)存警告的操作
- (void)didReceiveMemoryWarning;
必須調(diào)用super實(shí)現(xiàn)
協(xié)調(diào)系統(tǒng)手勢
-
preferredScreenEdgesDeferringSystemGestures
協(xié)調(diào)系統(tǒng)邊緣的滑動(dòng)手勢
@property(nonatomic, readonly) UIRectEdge preferredScreenEdgesDeferringSystemGestures;
有時(shí)候你的App需要控制從狀態(tài)欄下拉或者底部欄上滑,這個(gè)會(huì)跟系統(tǒng)的下拉通知中心手勢和上滑控制中心手勢沖突。
如果你要優(yōu)先自己處理手勢可以將系統(tǒng)手勢延遲。
《解決ios11上 從狀態(tài)欄下拉或底部欄上滑,跟系統(tǒng)的下拉通知中心手勢和上滑控制中心手勢沖突》
-
childViewControllerForScreenEdgesDeferringSystemGestures
控制子試圖控制器是否允許開發(fā)者控制edge protect的開啟或是關(guān)閉
@property(nonatomic, readonly) UIViewController *childViewControllerForScreenEdgesDeferringSystemGestures;
如果實(shí)現(xiàn)了這個(gè)方法并且返回值不為空那么子VC的edge protect設(shè)置就會(huì)遵循父VC的設(shè)置,跟隨父VC是否延遲執(zhí)行系統(tǒng)手勢。
《關(guān)于iPhone X下Home鍵的隱藏和延遲響應(yīng)》
管理狀態(tài)欄
-
childViewControllerForStatusBarStyle
應(yīng)該使用哪一個(gè)VC來確定狀態(tài)欄的Style
@property(nonatomic, readonly) UIViewController *childViewControllerForStatusBarStyle;
以下解釋轉(zhuǎn)自《iOS狀態(tài)欄詳解》
運(yùn)用這個(gè)函數(shù)就可以解決嵌套UINavigationController設(shè)置樣式無效的問題。
解釋一下為什么嵌套
UINavigationController的viewController的preferredStatusBarStyle函數(shù)設(shè)置無效:
在我們嵌套了UINavigationController的時(shí)候,我們的
AppDelegate.window.rootViewController
通常是我們創(chuàng)建的navigationController,這時(shí)首先會(huì)調(diào)用的是navigationController中的childViewControllerForStatusBarStyle函數(shù),因?yàn)槟J(rèn)返回nil,那么接下來就會(huì)調(diào)用navigationController本身的preferredStatusBarStyle函數(shù),所以我們?cè)?code>viewController中通過preferredStatusBarStyle函數(shù)設(shè)置的狀態(tài)欄樣式就不會(huì)被調(diào)用發(fā)現(xiàn),所以也就無效了。
所以我們要自己創(chuàng)建一個(gè)繼承于UINavigationcontroller的
NavigationController,在這個(gè)子類中重寫
childViewControllerForStatusBarStyle函數(shù)
- (UIViewController *)childViewControllerForStatusBarStyle{
return self.topViewController;
}
這樣navigationController中的childViewControllerForStatusBarStyle函數(shù)會(huì)返回navigationController中最上層的viewController,那么viewController中的preferredStatusBarStyle函數(shù)的設(shè)置就會(huì)被系統(tǒng)獲知。
-
childViewControllerForStatusBarHidden
應(yīng)該使用哪一個(gè)VC來確定狀態(tài)欄的顯示/隱藏
@property(nonatomic, readonly) UIViewController *childViewControllerForStatusBarHidden;
函數(shù)的使用原理同上,不再贅述。
-
preferredStatusBarStyle
狀態(tài)欄樣式
@property(nonatomic, readonly) UIStatusBarStyle preferredStatusBarStyle;
UIStatusBarStyle是一個(gè)枚舉類型
typedef NS_ENUM(NSInteger, UIStatusBarStyle) {
//默認(rèn)樣式,黑字透明狀態(tài)欄,適合用于背景色為亮色的頁面
UIStatusBarStyleDefault = 0, // Dark content, for use on light backgrounds
//白字透明狀態(tài)欄,適合用于背景色為暗色的頁面
UIStatusBarStyleLightContent NS_ENUM_AVAILABLE_IOS(7_0) = 1, // Light content, for use on dark backgrounds
// iOS7.0以前黑底白字,iOS7以后跟UIStatusBarStyleLightContent效果一樣
UIStatusBarStyleBlackTranslucent NS_ENUM_DEPRECATED_IOS(2_0, 7_0, "Use UIStatusBarStyleLightContent") = 1,
// iOS7.0以前啟動(dòng)頁為灰底白字,iOS7以后跟UIStatusBarStyleLightContent效果一樣
UIStatusBarStyleBlackOpaque NS_ENUM_DEPRECATED_IOS(2_0, 7_0, "Use UIStatusBarStyleLightContent") = 2,
} __TVOS_PROHIBITED;
使用起來、需要在具體的VC中
- (UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}
-
prefersStatusBarHidden
狀態(tài)欄的顯示/隱藏
@property(nonatomic, readonly) BOOL prefersStatusBarHidden;
使用起來、需要在具體的VC中
- (BOOL)prefersStatusBarHidden{
return YES;
}
-
modalPresentationCapturesStatusBarAppearance
在非全屏的模態(tài)中、獲得狀態(tài)欄控制權(quán)
@property(nonatomic, assign) BOOL modalPresentationCapturesStatusBarAppearance;
-
preferredStatusBarUpdateAnimation
狀態(tài)欄更新時(shí)的動(dòng)畫
@property(nonatomic, readonly) UIStatusBarAnimation preferredStatusBarUpdateAnimation;
重寫此方法設(shè)置狀態(tài)欄更新時(shí)候的動(dòng)畫
-
setNeedsStatusBarAppearanceUpdate
準(zhǔn)備更新狀態(tài)欄
- (void)setNeedsStatusBarAppearanceUpdate;
當(dāng)你需要更新狀態(tài)欄時(shí)、調(diào)用他。支持動(dòng)畫漸變
配置導(dǎo)航入口
-
navigationItem
分欄控制器按鈕
@property(nonatomic, readonly, strong) UINavigationItem *navigationItem;
可以用來設(shè)置導(dǎo)航欄上的分欄按鈕
UIBarButtonItem *rightItem = [[UIBarButtonItem alloc] initWithImage:[[UIImage imageNamed:@"nav_scan_icon.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] style:UIBarButtonItemStylePlain target:self action:@selector(rightItemAction)];
self.navigationItem.rightBarButtonItem = rightItem;
是UINavigationItem的唯一實(shí)例、通過懶加載的方式生產(chǎn)。
-
hidesBottomBarWhenPushed
在VC展示時(shí)、下方Tabbar是否隱藏
@property(nonatomic) BOOL hidesBottomBarWhenPushed;
通常都是在BaseViewController里設(shè)置成YES了。
-
toolbarItems
更改工具欄
- (void)setToolbarItems:(NSArray<UIBarButtonItem *> *)toolbarItems
animated:(BOOL)animated;
@property(nonatomic, strong) NSArray<__kindof UIBarButtonItem *> *toolbarItems;
-
tabBarItem
Tabbar上的按鈕
@property(nonatomic, strong) UITabBarItem *tabBarItem;
編輯行為
-
editing
是否允許用戶進(jìn)行編輯
@property(nonatomic, getter=isEditing) BOOL editing;
-
setEditing:animated:
更新Edit|Done按鈕item的外觀
- (void)setEditing:(BOOL)editing
animated:(BOOL)animated;
當(dāng)設(shè)置controller的editing屬性,會(huì)自動(dòng)觸發(fā)setEditing:animated屬性,這個(gè)時(shí)候通過myController editButtonItem獲得的編輯按鈕會(huì)自動(dòng)從edit變成Done,這個(gè)通常使用在navigation Controller
-
editButtonItem
返回Edit|Done按鈕。
@property(nonatomic, readonly) UIBarButtonItem *editButtonItem;
比如設(shè)置一個(gè)右上角按鈕為editButton的話代碼如下
myViewController.navigationItem.rightBarButtonItem=[myViewController editButtonItem];
參考資料
官方文檔-UIViewController
UIViewController詳解
iOS UIViewController
iOS開發(fā)之使用addChildViewController:給控制器添加子控制器
addChildViewController方法詳解
UIViewController全部API的學(xué)習(xí)
iOS開發(fā)之loadView、viewDidLoad及viewDidUnload的關(guān)系
iOS 中使用ViewController控制轉(zhuǎn)場的各種方法
edgesForExtendedLayout淺淡
解決ios11上 從狀態(tài)欄下拉或底部欄上滑,跟系統(tǒng)的下拉通知中心手勢和上滑控制中心手勢沖突
關(guān)于iPhone X下Home鍵的隱藏和延遲響應(yīng)
iOS:UIToolBar、toolbarItems、BarButtonItem的幾種關(guān)系