OC UIViewController基礎知識整理

韋家冰發表於2017-12-13

alloc init

//這個 方法是在viewdidload之前載入的,以nib檔案載入必然會呼叫此方法,但是程式碼載入也是會自動呼叫的,因此可以將一些陣列建立,標題命名等初始化操作寫在這裡
//1.如果在初始化UIViewController指定了xib檔名,就會根據傳入的xib檔名載入對應的xib檔案
//2.如果沒有明顯地傳xib檔名([[MJViewController alloc] init];),就會載入跟UIViewController同名的xib檔案
//3.如果沒有找到相關聯的xib檔案,就會建立一個空白的UIView,然後賦值給UIViewController的view屬性
- (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil NS_DESIGNATED_INITIALIZER;
//NSCoding協議
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;
//這個UIViewController的nib名字
@property(nullable, nonatomic, readonly, copy) NSString *nibName;
//這個UIViewController的nibBundle
@property(nullable, nonatomic, readonly, strong) NSBundle *nibBundle;
//這個UIViewControlle所在的Storyboar
@property(nullable, nonatomic, readonly, strong) UIStoryboard *storyboard NS_AVAILABLE_IOS(5_0);
複製程式碼

loadView

//如果獲取self.view,如果沒有現實[self loadView],就是呼叫Subclasses的loadView方法。
@property(null_resettable, nonatomic,strong) UIView *view;

//loadView裡面自定義self.view
- (void)loadView;

//iOS9之前
//有些時候因為需要手動呼叫loadview
//但是有風險,系統不再呼叫viewDidLoad
//所以手動呼叫loadview是錯誤的

//iOS9之後
//出現了loadViewIfNeeded解決了這個問題
//呼叫這個方法檢視會建立出來並且不會忽略viewDidLoad
- (void)loadViewIfNeeded NS_AVAILABLE_IOS(9_0);

//返回載入完的self.view
@property(nullable, nonatomic, readonly, strong) UIView *viewIfLoaded NS_AVAILABLE_IOS(9_0);

//view是否載入完成
@property(nonatomic, readonly, getter=isViewLoaded) BOOL viewLoaded ;
- (BOOL)isViewLoaded ;
複製程式碼

Storyboary相關

//Storyboar跳轉擺好的介面
//identifier:設定好的介面連線(就是Storyboar中VC與VC那條線)
//sender:傳送者
- (void)performSegueWithIdentifier:(NSString *)identifier sender:(nullable id)sender NS_AVAILABLE_IOS(5_0);

//看看能不能跳轉,主要是看identifier對不對
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(nullable id)sender NS_AVAILABLE_IOS(6_0);


//準備處理,
//segue:用來判斷是哪個segue,裡面有identifier、sourceViewController、destinationViewController可以各種操作
//sender:傳送者
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(nullable id)sender NS_AVAILABLE_IOS(5_0);

//Unwind Segue相關,(不明白,留著慢慢玩)
- (BOOL)canPerformUnwindSegueAction:(SEL)action fromViewController:(UIViewController *)fromViewController withSender:(id)sender NS_AVAILABLE_IOS(6_0);
- (NSArray<UIViewController *> *)allowedChildViewControllersForUnwindingFromSource:(UIStoryboardUnwindSegueSource *)source NS_AVAILABLE_IOS(9_0);
- (nullable UIViewController *)childViewControllerContainingSegueSource:(UIStoryboardUnwindSegueSource *)source NS_AVAILABLE_IOS(9_0);
- (nullable UIViewController *)viewControllerForUnwindSegueAction:(SEL)action fromViewController:(UIViewController *)fromViewController withSender:(nullable id)sender NS_DEPRECATED_IOS(6_0, 9_0);
- (void)unwindForSegue:(UIStoryboardSegue *)unwindSegue towardsViewController:(UIViewController *)subsequentVC NS_AVAILABLE_IOS(9_0);
- (nullable UIStoryboardSegue *)segueForUnwindingToViewController:(UIViewController *)toViewController fromViewController:(UIViewController *)fromViewController identifier:(nullable NSString *)identifier NS_DEPRECATED_IOS(6_0, 9_0);
複製程式碼

生命週期函式

//系統的loadview完成後,執行viewDidLoad
- (void)viewDidLoad;
//這幾個生命週期方法,必須熟悉
- (void)viewWillAppear:(BOOL)animated;
- (void)viewDidAppear:(BOOL)animated;
- (void)viewWillDisappear:(BOOL)animated;
- (void)viewDidDisappear:(BOOL)animated;
- (void)viewWillLayoutSubviews NS_AVAILABLE_IOS(5_0);
- (void)viewDidLayoutSubviews NS_AVAILABLE_IOS(5_0);
- (void)didReceiveMemoryWarning;
複製程式碼

單個viewController的生命週期

1、initWithCoder:(NSCoder *)aDecoder:(如果使用storyboard或者xib)
2、loadView:載入view
3、viewDidLoad:view載入完畢
4、viewWillAppear:控制器的view將要顯示
5、viewWillLayoutSubviews:控制器的view將要佈局子控制元件
6、viewDidLayoutSubviews:控制器的view佈局子控制元件完成,這期間系統可能會多次呼叫viewWillLayoutSubviews 、    viewDidLayoutSubviews 倆個方法
7、viewDidAppear:控制器的view完全顯示
8、viewWillDisappear:控制器的view即將消失的時候
9、這期間系統也會呼叫viewWillLayoutSubviews 、viewDidLayoutSubviews 兩個方法
10、viewDidDisappear:控制器的view完全消失的時候
複製程式碼

多個viewControllers跳轉

當我們點選push的時候首先會載入下一個介面然後才會呼叫介面的消失方法
1、initWithCoder:(NSCoder *)aDecoder:ViewController2 (如果用xib建立的情況下)
2、loadView:ViewController2
3、viewDidLoad:ViewController2
4、viewWillDisappear:ViewController1 將要消失
5、viewWillAppear:ViewController2 將要出現
6、viewWillLayoutSubviews ViewController2
7、viewDidLayoutSubviews ViewController2
8、viewWillLayoutSubviews:ViewController1
9、viewDidLayoutSubviews:ViewController1
10、viewDidDisappear:ViewController1 完全消失
11、viewDidAppear:ViewController2 完全出現
複製程式碼
//nav標題
@property(nullable, nonatomic,copy) NSString *title;

@property(nullable,nonatomic,weak,readonly) UIViewController *parentViewController;//父控制器
@property(nullable, nonatomic,readonly) UIViewController *presentedViewController;//第二者
@property(nullable, nonatomic,readonly) UIViewController *presentingViewController;//第一者

//例子
UIViewController *vcB = [[UIViewController alloc] init];
[self addChildViewController:vcB];
NSLog(@"%@", vcB.parentViewController);//self

UIViewController *vcB = [[UIViewController alloc] init];
[self presentViewController:vcB animated:YES completion:^{}];
    
NSLog(@"%@", self.presentedViewController);//vcB
NSLog(@"%@", self.presentingViewController);//nil
    
NSLog(@"%@", vcB.presentedViewController);//nil
NSLog(@"%@", vcB.presentingViewController);//self

複製程式碼
//UIViewController的edgesForExtendedLayout屬性預設值是UIRectEdgeAll,指定控制器將它的檢視延伸到螢幕的邊緣並在bar下面。如果屬性值為:UIRectEdgeNone,控制器檢視遇到bar的邊界就不延伸了。
@property(nonatomic,assign) UIRectEdge edgesForExtendedLayout ; // Defaults to UIRectEdgeAll

//UIViewController的extendedLayoutIncludesOpaqueBars屬性可以控制以上屬性的有效性,預設值為NO,指定edgesForExtendedLayout在遇到不透明的bar時無效,即不延展。設定值為YES,則在遇到透明或不透明的bar情況下都會延展。
@property(nonatomic,assign) BOOL extendedLayoutIncludesOpaqueBars ; // Defaults to NO, but bars are translucent by default on 7_0.

//UIViewController的automaticallyAdjustsScrollViewInsets預設為YES,指定控制器在有UIScrollView及其子類並且在有導航欄或工具欄或標籤欄情況下,會自動調整其contentInset屬性。如果是導航欄contentInset.top = 64,如果是標籤欄contentInset.bottom = 44.
//可以將該屬性設定為NO,取消這種行為。
@property(nonatomic,assign) BOOL automaticallyAdjustsScrollViewInsets ; // Defaults to YES
複製程式碼

UIStatusBar相關的設定iOS-UIStatusBar詳細總結

- (UIStatusBarStyle)preferredStatusBarStyle ;
- (BOOL)prefersStatusBarHidden ;
- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation
複製程式碼

UIModalTransitionStyle是彈出模態ViewController時的四種動畫風格

typedef NS_ENUM(NSInteger, UIModalTransitionStyle) {
    UIModalTransitionStyleCoverVertical = 0,//是從底部滑入,預設
    UIModalTransitionStyleFlipHorizontal ,  //是水平翻轉
    UIModalTransitionStyleCrossDissolve,    //是交叉溶解
    UIModalTransitionStylePartialCurl,      //是翻書效果
};
複製程式碼

UIModalPresentationStyle是彈出模態ViewController時彈出風格 Present ViewController詳解

typedef NS_ENUM(NSInteger, UIModalPresentationStyle) {
    UIModalPresentationFullScreen = 0,      //是彈出VC時,VC充滿全屏
    UIModalPresentationPageSheet ,          //是如果裝置橫屏,VC的顯示方式則從橫屏下方開始
    UIModalPresentationFormSheet ,          //是VC顯示都是從底部,寬度和螢幕寬度一樣
    UIModalPresentationCurrentContext ,     //是VC的彈出方式和VC父VC的彈出方式相同
    UIModalPresentationCustom ,             //自定義
    UIModalPresentationOverFullScreen ,     //
    UIModalPresentationOverCurrentContext , //
    UIModalPresentationPopover ,            //
    UIModalPresentationNone ,               //
};
複製程式碼

如何present一個半透明的ViewController

- (void)btnOnClick:(id)sender {
    UIViewController *test = [[UIViewController alloc] init];
    self.definesPresentationContext = YES;
    test.view.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:.4];
    test.modalPresentationStyle = UIModalPresentationOverCurrentContext;
    [self presentViewController:test animated:YES completion:nil];
}
複製程式碼

UIContentContainer iOS8之後,加入了新的一組協議,UIViewController對這組協議提供了預設的實現,我們自定義ViewConttroller的時候可以重寫這些方法來調整檢視佈局。(先放放,等有時間在研究使用)

@protocol UIContentContainer <NSObject>

@property (nonatomic, readonly) CGSize preferredContentSize NS_AVAILABLE_IOS(8_0);

//當一個容器ViewController的ChildViewController的preferredContentSize值改變時,UIKit會呼叫這個方法告訴當前容器ViewController。我們可以在這個方法里根據新的Size對介面進行調整。
- (void)preferredContentSizeDidChangeForChildContentContainer:(id <UIContentContainer>)container NS_AVAILABLE_IOS(8_0);

//當一個容器ViewController的ChildViewController的systemLayoutFittingSize值改變時,UIKit會呼叫這個方法告訴當前容器ViewController。我們可以在這個方法里根據新的Size對介面進行調整。
- (void)systemLayoutFittingSizeDidChangeForChildContentContainer:(id <UIContentContainer>)container NS_AVAILABLE_IOS(8_0);

//viewWillTransitionToSize:withTransitionCoordinator:呼叫的時候
- (CGSize)sizeForChildContentContainer:(id <UIContentContainer>)container withParentContainerSize:(CGSize)parentSize NS_AVAILABLE_IOS(8_0);

//TransitionToSize:動畫方面觸發?
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator NS_AVAILABLE_IOS(8_0);

//什麼鬼啊?
- (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator NS_AVAILABLE_IOS(8_0);

@end
複製程式碼

相關文章