iOS文檔補(bǔ)完計(jì)劃--UIViewController

目錄

  • 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é)
  1. 更新視圖內(nèi)容
  2. 響應(yīng)交互
  3. 調(diào)整入口View布
  4. 與程序中其他對(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:

  1. Storyboard
    可以指定視圖及其與視圖控制器的連接。
    你也指定視圖控制器之間的關(guān)系和segue。
  2. Nib
    使用Nib文件為視圖控制器指定單個(gè)視圖控制器的視圖。
    但不允許定義segue或視圖控制器之間的關(guān)系。
  3. 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)存。

  • 生命周期
  1. +[ViewController load]
  2. +[ViewController initialize]
  3. -[ViewController init]
  4. -[ViewController loadView]
  5. -[ViewController viewDidLoad]
  6. -[ViewController viewWillAppear:]
  7. -[ViewController updateViewConstraints]
  8. -[ViewController viewWillLayoutSubviews]
  9. -[ViewController viewDidLayoutSubviews]
  10. -[ViewController viewDidAppear:]
  11. -[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;
  1. 這個(gè)屬性是來加載的、當(dāng)你訪問時(shí)如果為nil、將調(diào)用loadView方法并返回view
  2. 每一個(gè)VC、都必須是該View的唯一一個(gè)持有者。(例外情況是通過addChildViewController:方法添加后、將vc.view add給另一個(gè)vc)
  3. 你可以通過isViewLoaded方法來檢測當(dāng)前vc是否已經(jīng)持有視圖。(這樣不會(huì)觸發(fā)懶加載)。
  4. 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屬性的視圖。

  1. 永遠(yuǎn)不要直接調(diào)用這個(gè)方法。
  2. 如果使用nib、該方法從nib中加載視圖。如果不是、則直接創(chuàng)建一個(gè)UIView。
  3. 如果使用IB來創(chuàng)建VC、不要覆蓋這個(gè)方法。
  4. 如果自定義view。您創(chuàng)建的視圖應(yīng)該是唯一的實(shí)例,不應(yīng)該與任何其他視圖控制器對(duì)象共享。此方法的自定義實(shí)現(xiàn)不應(yīng)調(diào)用super。
  5. 如果想對(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.titlenavigationItem.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方式來切換界面。

showViewController是蘋果“大一統(tǒng)”編程思想的體現(xiàn),無論是在UINavigationController還是在UISplitViewController管理下,都可以使用showViewController去跳轉(zhuǎn)。系統(tǒng)底層會(huì)實(shí)現(xiàn)兩種管理模式下的對(duì)應(yīng)跳轉(zhuǎn)。另外如果這兩種方式都未實(shí)現(xiàn),就會(huì)以modal方式跳轉(zhuǎn)。

  1. 當(dāng)前界面是Nav的子VC時(shí)
    它會(huì)用push方式切換。
  2. 當(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ì)起作用

《edgesForExtendedLayout淺淡》

  • 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)用childviewWillAppear或者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ā)viewDidAppearviewDidDisappear。


響應(yīng)容器事件

  • - willMoveToParentViewController

將要添加到容器VC時(shí)調(diào)用

- (void)willMoveToParentViewController:(UIViewController *)parent;

BVC通過addChildViewControllerA、接口建立了邏輯上的父子關(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è)置樣式無效的問題。

解釋一下為什么嵌套UINavigationControllerviewControllerpreferredStatusBarStyle函數(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;

modalPresentationCapturesStatusBarAppearance是專門為強(qiáng)迫癥患者量身定制的,只需要重寫這個(gè)屬性并返回true,你就可以在任何形式的Model Presentation中獲得對(duì) Status Bar Style的控制權(quán)了。

  • 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è)置controllerediting屬性,會(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)系

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容