美文网首页
UIViewController学习笔记

UIViewController学习笔记

作者: 寻心_0a46 | 来源:发表于2019-11-20 23:29 被阅读0次

UIViewController是一个为UIKit应用管理视图层次结构的对象,定义了所有视图控制器通用的共享行为,很少直接创建UIViewController类的实例,通常可以将UIViewController子类化,并添加管理视图控制器的视图层次结构所需的方法和属性。

视图控制器的主要职责包括:

  • 更新视图的内容,通常是为了响应对基础数据的更改。
  • 使用视图响应用户交互。
  • 调整视图大小并管理整个界面的布局。
  • 与其他对象协调,包括应用程序中的其他视图控制器。

视图控制器与它所管理的视图紧密绑定,并参与处理其视图层次结构中的事件。具体地说,视图控制器是UIResponder对象,被插入到视图控制器的根视图和该视图的superview之间的响应程序链中,superview通常属于不同的视图控制器。如果视图控制器的视图都不处理事件,则视图控制器可以选择处理事件或将其传递给超级视图。

视图控制器很少单独使用,通常使用多个视图控制器,每个视图控制器拥有应用程序用户界面的一部分。例如,一个视图控制器可能显示一个项目表,而另一个视图控制器显示该表中选定的项目。通常,一次只有一个视图控制器中的视图可见。视图控制器可以提供不同的视图控制器来显示一组新的视图,或者它可以充当其他视图控制器内容的容器,并根据需要设置视图动画。

例如:

截屏2020-11-12上午10.50.30.png

UIViewController生命周期相关函数

- (void)loadView;

函数摘要:创建控制器管理的视图。如果子类不使用nib,那么应该在这里创建它们的自定义视图层次结构。不应该直接调用。视图控制器在请求其视图属性但当前为空时调用此方法。

- (void)loadView;

- (void)viewDidLoad;

函数摘要:在控制器的视图加载到内存中后调用。对于在代码中创建的视图控制器,这是在-loadView之后。对于未从nib存档的视图控制器,这是在设置视图之后。

- (void)viewDidLoad; 

- (void)viewWillAppear:(BOOL)animated;

函数摘要:通知视图控制器其视图将被添加到视图层次结构中,当视图即将显示前调用,需要子类进行覆盖,默认什么都不做。

- (void)viewWillAppear:(BOOL)animated; 

- (void)viewDidAppear:(BOOL)animated;

函数摘要:通知视图控制器其视图已添加到视图层次结构中,当视图完全显示到屏幕上时调用,需要子类进行覆盖,默认什么都不做。

- (void)viewDidAppear:(BOOL)animated;

- (void)viewWillDisappear:(BOOL)animated;

函数摘要:通知视图控制器其视图即将从视图层次结构中移除,当视图被移除、覆盖或隐藏时调用。需要子类进行覆盖,默认什么都不做。

- (void)viewWillDisappear:(BOOL)animated; 

- (void)viewDidDisappear:(BOOL)animated;

函数摘要:通知视图控制器其视图已从视图层次结构中移除,在视图被移除、覆盖或隐藏后调用。需要子类进行覆盖,默认什么都不做。

- (void)viewDidDisappear:(BOOL)animated;

- (void)didReceiveMemoryWarning;

函数摘要:当父应用程序收到内存警告时调用。在iOS 6.0上,默认情况下它将不再清除视图。

- (void)didReceiveMemoryWarning;

- (void)viewWillUnload API_DEPRECATED("", ios(5.0, 6.0)) API_UNAVAILABLE(tvOS);

函数摘要:在从内存中释放控制器视图之前调用。

- (void)viewWillUnload API_DEPRECATED("", ios(5.0, 6.0)) API_UNAVAILABLE(tvOS);

- (void)viewDidUnload API_DEPRECATED("", ios(3.0, 6.0)) API_UNAVAILABLE(tvOS);

函数摘要:当控制器的视图从内存中释放时调用。在视图控制器的视图被释放并设置为nil后调用。例如,一个导致视图被清除的内存警告。没有调用-dealloc的结果。

- (void)viewDidUnload API_DEPRECATED("", ios(3.0, 6.0)) API_UNAVAILABLE(tvOS); 

控制器视图布局其子视图相关函数

- (void)loadViewIfNeeded API_AVAILABLE(ios(9.0));

函数摘要:如果尚未设置视图控制器的视图,则加载该视图控制器的视图。

- (void)loadViewIfNeeded API_AVAILABLE(ios(9.0));

- (void)viewWillLayoutSubviews API_AVAILABLE(ios(5.0));

函数摘要:调用此函数以通知视图控制器其视图即将布局其子视图。在调用视图控制器的视图的layoutSubviews方法之前调用。子类可以根据需要实现。默认值是nop。

- (void)viewWillLayoutSubviews API_AVAILABLE(ios(5.0));

- (void)viewDidLayoutSubviews API_AVAILABLE(ios(5.0));

函数摘要:调用此函数以通知视图控制器其视图刚刚布局了其子视图。在调用视图控制器的视图的layoutSubviews方法之后调用。子类可以根据需要实现。默认值是nop。

- (void)viewDidLayoutSubviews API_AVAILABLE(ios(5.0));

模态呈现控制器相关函数

- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^ __nullable)(void))completion API_AVAILABLE(ios(5.0));

函数摘要:以模态呈现视图控制器。

参数描述:

viewControllerToPresent:要在当前视图控制器的内容上显示的视图控制器。

flag:是否显示动画。

completion:显示完成后要执行的块。此块没有返回值,不接受任何参数。可以为此参数指定nil。

- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^ __nullable)(void))completion API_AVAILABLE(ios(5.0));

- (void)dismissViewControllerAnimated: (BOOL)flag completion: (void (^ __nullable)(void))completion API_AVAILABLE(ios(5.0));

函数摘要:解除视图控制器以模式显示的视图控制器。

参数描述:

flag:是否显示动画。

completion:解除视图控制器后要执行的块。此块没有返回值,不接受任何参数。可以为此参数指定nil。

- (void)dismissViewControllerAnimated: (BOOL)flag completion: (void (^ __nullable)(void))completion API_AVAILABLE(ios(5.0));

添加子控制器到父控制器相关函数

有时为了在一个本就已经比较复杂的页面增加功能时,可以将要增加的视图交由一个新的控制器去管理,然后将新的视图控制器添加至父视图控制器,从而更清晰的管理页面视图的逻辑。例如为了灵活的放置子视图控制器位置,并且将页面的逻辑单独由一个控制器去处理,采用添加子控制器到父控制器的方式显示视图控制器:

截屏2021-05-25下午6.46.48.png

添加视图控制器的代码片段:

///以添加子控制器的方式打开店铺分类选择视图控制器
- (void)openShopCategorySelectViewController:(UIViewController *)controller{
    //判读打开店铺分类选择视图控制器的是否是店铺根视图控制器
    if([controller isMemberOfClass:[YSCShopViewController class]]){
        //是店铺根视图控制器
        self.shopCategorySelectViewController.view.frame = CGRectMake(0, 0, ScreenWidth, ScreenHeight - 44 - bottomPadding());
    }else{
        //其他视图控制器
        self.shopCategorySelectViewController.view.frame = CGRectMake(0, 0, ScreenWidth, ScreenHeight - HEAD_BAR_HEIGHT - 44 - bottomPadding());
    }
    //添加店铺分类选择视图控制器到当前视图控制器
    [controller addChildViewController:self.shopCategorySelectViewController];
    //在调用addChildViewController:方法后需要调用
    [self.shopCategorySelectViewController didMoveToParentViewController:controller];
    //设置视图切换控制器视图在其父视图边界更改时调整自身的方式
    self.shopCategorySelectViewController.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
    //添加视图切换控制器视图
    [controller.view addSubview:self.shopCategorySelectViewController.view];
}

- (void)addChildViewController:(UIViewController *)childController API_AVAILABLE(ios(5.0));

函数摘要 : 将指定的视图控制器添加为当前视图控制器的子视图控制器。该方法在当前视图控制器和childController参数中的对象之间创建父子关系。当将子视图控制器的视图嵌入到当前视图控制器的内容中时,这种关系是必要的。如果新的子视图控制器已经是容器视图控制器的子控制器,它在被添加之前会从容器中移除。

此方法仅用于自定义容器视图控制器的实现来调用。如果重写此方法,则必须在实现中调用super。

参数描述:

childController:要作为子级添加的视图控制器。

- (void)addChildViewController:(UIViewController *)childController API_AVAILABLE(ios(5.0));

注:添加子视图控制器后,也需要通过addSubview将子ViewController的view添加到父视图的视图层级中。

- (void)didMoveToParentViewController:(nullable UIViewController *)parent API_AVAILABLE(ios(5.0));

函数摘要:在从容器视图控制器添加或删除视图控制器后调用。当视图控制器希望在被添加到容器视图控制器或在容器视图控制器中被移除之后做出某些反应时,视图控制器(被添加的视图控制器)可以重写这个方法。从容器视图控制器过渡到被添加的视图控制器后,会调用被添加的视图控制器重写的didMoveToParentViewController:方法,但前提是在调用addChildViewController:方法后立即调用了didMoveToParentViewController:方法。

removeFromParentViewController方法在移除子视图控制器后自动调用子视图控制器重写的didMoveToParentViewController:方法。

参数描述:

parent:父视图控制器,如果没有父视图控制器,则为nil。

- (void)didMoveToParentViewController:(nullable UIViewController *)parent API_AVAILABLE(ios(5.0));

移除视图控制器的代码片段:

///移除店铺分类选择视图控制器
- (void)removeShopCategorySelectViewController{
    [self.view endEditing:YES];
    //在容器视图控制器中添加或删除视图控制器之前调用
    [self willMoveToParentViewController:nil];
    //在父视图移除视图
    [self.view removeFromSuperview];
    //从其父视图控制器中删除视图控制器
    [self removeFromParentViewController];
}

- (void)willMoveToParentViewController:(nullable UIViewController *)parent API_AVAILABLE(ios(5.0));

函数摘要:在视图控制器从容器视图控制器中添加或删除之前调用。当视图控制器希望在被添加到容器视图控制器或在容器视图控制器中被移除之前做出某些反应时,视图控制器(被添加的视图控制器)可以重写这个方法。容器视图控制器调用addChildViewController:方法时,会自动调用要作为子级添加的视图控制器重写的willMoveToParentViewController:方法。但作为子级添加的视图控制器在调用removeFromParentViewController在容器视图控制器中移除之前,必须调用willMoveToParentViewController:方法并传入nil值。

参数描述 :

parent :父视图控制器,如果没有父视图控制器则为nil。

- (void)willMoveToParentViewController:(nullable UIViewController *)parent API_AVAILABLE(ios(5.0));

- (void)removeFromParentViewController API_AVAILABLE(ios(5.0));

函数摘要 :从其父视图控制器中移除视图控制器。此方法仅用于由自定义容器视图控制器的实现调用。如果重写此方法,则必须在实现中调用super。

- (void)removeFromParentViewController API_AVAILABLE(ios(5.0));

常用属性

@property(null_resettable, nonatomic,strong) UIView *view;

属性描述:控制器管理的视图。如果尚未设置视图,getter首先调用[self loadView]。如果子类重写setter或getter,则必须调用super。

@property(null_resettable, nonatomic,strong) UIView *view;

@property(nullable, nonatomic, readonly, strong) UIView *viewIfLoaded API_AVAILABLE(ios(9.0));

属性描述 : 如果已加载,则返回视图控制器的视图;如果未加载,则返回nil。

@property(nullable, nonatomic, readonly, strong) UIView *viewIfLoaded API_AVAILABLE(ios(9.0));

@property(nonatomic, readonly, getter=isViewLoaded) BOOL viewLoaded API_AVAILABLE(ios(3.0));

属性描述 : 一个布尔值,指示视图当前是否已加载到内存中。当视图在内存中时,此属性的值为“YES”,否则为“NO”。

@property(nonatomic, readonly, getter=isViewLoaded) BOOL viewLoaded API_AVAILABLE(ios(3.0));

@property(nullable, nonatomic,copy) NSString *title;

属性描述 : 父控制器使用的本地化标题。

@property(nullable, nonatomic,copy) NSString *title; 

@property(nullable,nonatomic,weak,readonly) UIViewController *parentViewController;

属性描述: 如果此视图控制器是包含视图控制器(例如导航控制器或选项卡栏控制器)的子控制器,则这是包含视图控制器(返回的父视图控制器,如果该视图控制器没有父级,则此属性中的值为nil)。注意,从5.0开始,这将不再返回呈现视图控制器。

@property(nullable,nonatomic,weak,readonly) UIViewController *parentViewController;

@property(nullable, nonatomic,readonly) UIViewController *presentedViewController API_AVAILABLE(ios(5.0));

属性描述 : 当使用 - (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^ __nullable)(void))completion);以模态(显式或隐式)呈现视图控制器时,调用该方法的视图控制器将此属性设置为其呈现的视图控制器。如果当前视图控制器没有以模式显示另一个视图控制器,则此属性中的值为nil。

@property(nullable, nonatomic,readonly) UIViewController *presentedViewController  API_AVAILABLE(ios(5.0));

@property(nullable, nonatomic,readonly) UIViewController *presentingViewController API_AVAILABLE(ios(5.0));

属性描述 : 显示此视图控制器的视图控制器。当使用presentViewController:animated:completion: method 模态(显式或隐式)呈现一个视图控制器时,被呈现的视图控制器将这个属性设置为呈现它的视图控制器。如果视图控制器不是以模态方式呈现的,但它的一个祖先是,这个属性包含呈现祖先的视图控制器。如果当前视图控制器或其任何祖先都没有以模态方式显示,则此属性中的值为nil。

@property(nullable, nonatomic,readonly) UIViewController *presentingViewController API_AVAILABLE(ios(5.0));

@property(nonatomic,assign) UIModalPresentationStyle modalPresentationStyle API_AVAILABLE(ios(3.2));

属性描述 : 定义此视图控制器以模式显示时将使用的表示样式。在将要呈现的视图控制器(而不是它的呈现者)上设置此属性。

如果此属性已设置为UIModalPresentationAutomatic,则读取它将始终返回具体的表示样式。

默认情况下,UIViewController将UIModalPresentationAutomatic解析为UIModalPresentationPageSheet,但系统提供的子类可以将UIModalPresentationAutomatic解析为其他具体的表示样式。系统提供的视图控制器保留对UIModalPresentationAutomatic解析的参与。

从iOS 13.0开始,在iOS上默认为UIModalPresentationAutomatic,在早期版本上默认为UIModalPresentationFullScreen。在所有其他平台上默认为UIModalPresentationFullScreen。

@property(nonatomic,assign) UIModalPresentationStyle modalPresentationStyle API_AVAILABLE(ios(3.2));

@property(nonatomic,assign) BOOL definesPresentationContext API_AVAILABLE(ios(5.0));

属性描述 : 一个布尔值,指示当视图控制器或其后代之一呈现视图控制器时是否覆盖该视图控制器的视图。当使用UIModalPresentationCurrentContext或UIModalPresentationOverCurrentContext样式来呈现一个视图控制器时,这个属性控制在你的视图控制器层次结构中哪些现有的视图控制器实际上被新内容覆盖。当一个基于上下文的表示发生时,UIKit从表示视图控制器开始并向上走到视图控制器层次结构。如果它找到一个视图控制器,它的这个属性的值是YES,它会请求那个视图控制器呈现新的视图控制器。如果没有视图控制器定义表示上下文,UIKit会请求窗口的根视图控制器来处理表示。此属性的默认值为NO。一些系统提供的视图控制器,如UINavigationController,将默认值更改为YES。

@property(nonatomic,assign) BOOL definesPresentationContext API_AVAILABLE(ios(5.0));

@property(nonatomic,assign) UIModalTransitionStyle modalTransitionStyle API_AVAILABLE(ios(3.0));

属性描述 : 显示视图控制器时要使用的转换样式。此属性确定当视图控制器使用presentViewController:animated:completion:函数显示时,如何在屏幕上设置其动画。若要更改转换类型,必须在显示视图控制器之前设置此属性。此属性的默认值为UIModalTransitionStyleCoverVertical。

@property(nonatomic,assign) UIModalTransitionStyle modalTransitionStyle API_AVAILABLE(ios(3.0));

UIModalTransitionStyle提供的枚举值:

typedef NS_ENUM(NSInteger, UIModalTransitionStyle) {
    //显示视图控制器时,其视图从屏幕底部向上滑动。解除显示时,视图向下滑动。这是默认的过渡样式。
    UIModalTransitionStyleCoverVertical = 0,
    //显示视图控制器时,当前视图将启动从右到左的水平三维翻转,从而显示新视图,就像它位于前一视图的背面一样。解除显示时,从左向右翻转,返回到原始视图。
    UIModalTransitionStyleFlipHorizontal API_UNAVAILABLE(tvOS),
    //显示视图控制器时,当前视图淡出,而新视图同时淡入。取消时,将使用类似类型的交叉淡入淡出来返回原始视图。
    UIModalTransitionStyleCrossDissolve,
    //显示视图控制器时,当前视图的一个角向上卷曲以显示下面显示的视图。在撤销时,卷曲的页面将自己展开回到显示视图的顶部。使用此转换显示的视图控制器本身无法显示任何其他视图控制器。仅当父视图控制器呈现全屏视图并且您使用UIModalPresentationFullScreen模式呈现样式时,才支持此转换样式。尝试对父视图使用不同的形状因子或不同的表示样式会触发异常。
    UIModalTransitionStylePartialCurl API_AVAILABLE(ios(3.2)) API_UNAVAILABLE(tvOS),
};

例如设置水平三维翻转显示控制器的代码片段:

YISVlogTabBarController1 *vlog = [[YISVlogTabBarController1 alloc]init];
vlog.modalPresentationStyle = UIModalPresentationFullScreen;
vlog.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:vlog animated:YES completion:nil];

样式如图 :

记录的代码片段

获取当前视图所在控制器的代码片段 :

- (UIViewController *)getCurrentVC{
    
    UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
    UIViewController *currentVC = [self getCurrentVCFrom:rootViewController];
    return currentVC;
}

- (UIViewController *)getCurrentVCFrom:(UIViewController *)rootVC{
    
    UIViewController *currentVC;
    if ([rootVC presentedViewController]) {
      
        rootVC = [rootVC presentedViewController];
    }
    
    if ([rootVC isKindOfClass:[UITabBarController class]]) {

        currentVC = [self getCurrentVCFrom:[(UITabBarController *)rootVC selectedViewController]];
        
    } else if ([rootVC isKindOfClass:[UINavigationController class]]){
     
        currentVC = [self getCurrentVCFrom:[(UINavigationController *)rootVC visibleViewController]];
        
    } else {
       
        currentVC = rootVC;
    }
    
    return currentVC;
}

既有模态显示又有push显示时,返回根控制 :

- (void)backToRootViewController{
    //获取当前视图控制器
    UIViewController *currentVC = [self getCurrentVC];
    //如果当前控制器是以模态显示的
    while(currentVC.presentingViewController != nil){
         //获取模态显示当前视图控制器的视图控制器
        currentVC = currentVC.presentingViewController;
         //模态的关闭显示当前视图控制器的视图控制器
        [currentVC dismissViewControllerAnimated:NO completion:nil];
    }
    //返回根视图控制器
    [currentVC.navigationController popToRootViewControllerAnimated:NO];
}

相关文章

网友评论

      本文标题:UIViewController学习笔记

      本文链接:https://www.haomeiwen.com/subject/drtzvctx.html