UINavigationController 导航控制器

当程序需要显示具有层次化的界面,帮助我们跳转页面的时候,需要使用UINavigationController

导航控制器的创建及使用

  1. 构造方法
1. 通过自定义 NavigationBar 来创建 UINavigationController
	- (instancetype)initWithNavigationBarClass:(nullable Class)navigationBarClass toolbarClass:(nullable Class)toolbarClass;
2. 通过设置根控制器创建
- (instancetype)initWithRootViewController:(UIViewController *)rootViewController; 
  1. 常用属性
1. 栈顶控制器
	@property(nullable, nonatomic,readonly,strong) UIViewController *topViewController;
2. 可见控制器
@property(nullable, nonatomic,readonly,strong) UIViewController *visibleViewController;
3. 栈当中的控制器数组
@property(nonatomic,copy) NSArray<__kindof UIViewController *> *viewControllers;
4. 控制器当中的上控制栏
@property(nonatomic,readonly) UINavigationBar *navigationBar;
5. 控制器当中的底栏
@property(null_resettable,nonatomic,readonly) UIToolbar *toolbar;
6. 代理对象
@property(nullable, nonatomic, weak) id delegate;
7. 边缘侧滑返回手势
@property(nullable, nonatomic, readonly) UIGestureRecognizer *interactivePopGestureRecognizer;
  1. UINavigationController 当中的常用方法
1. 将参数当中的控制器推入栈中且刷新屏幕。(注意:这个方法不能随便使用,否则编译器运行时报界面找不到。)
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated;
2. 弹出当前导航控制器栈顶的控制器并且刷新屏幕
- (nullable UIViewController *)popViewControllerAnimated:(BOOL)animated;
3. 弹出所有除根控制器以外在栈当中的控制器并且刷新屏幕
- (nullable NSArray<__kindof UIViewController *> *)popToRootViewControllerAnimated:(BOOL)animated;
4. 将栈中的控制器弹出直到指定的控制器位于导航控制器栈的顶端
- (nullable NSArray<__kindof UIViewController *> *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated;
  1. UINavigationItem 当中常用属性
1. 导航栏标题
@property(nullable, nonatomic, copy)   NSString *title;  
2. 导航栏左边的项目
@property(nullable, nonatomic, strong) UIBarButtonItem *leftBarButtonItem;
如果需要设置是否点击以后有动画,需要调用 - (void)setLeftBarButtonItem:(nullable UIBarButtonItem *)item animated:(BOOL)animated; 方法
3. 导航栏左边多个项目
@property(nullable,nonatomic,copy) NSArray *leftBarButtonItems;
4. 导航栏右边的项目
@property(nullable, nonatomic, strong) UIBarButtonItem *rightBarButtonItem;
如果需要设置是否点击以后有动画,需要调用 - (void)setRightBarButtonItem:(nullable UIBarButtonItem *)item animated:(BOOL)animated; 方法
5. 导航栏右边多个项目
@property(nullable,nonatomic,copy) NSArray *rightBarButtonItems;
6. 设置除展示返回键以外是否展示其他按钮。The value in the hidesBackButton property still determines whether the back button is actually displayed.
@property(nonatomic) BOOL leftItemsSupplementBackButton

注意:在设置UIBarButtonItem的时候,不能设置重复的选项,否则会出现显示不正常

  1. 通过 StoryBoard 创建导航控制器
    1. 先在 Storyboard 上拖一个 UINavigationController
    2. 如果不需要 rootController ,则将 rootController 删除,再将需要设置成 rootController 的控制器通过连线的方式进行设置。
      (注意:这个 rootController 才是真正显示在界面的控制器, UINavigationController 只是负责控制器之间的跳转操作。)
    3. 将需要从 A 控制器点击跳转到 B 控制器当中的按钮拖线到 B 控制器。选择 show 选项,这样 A 控制器就有一条 segue 通向 B 控制器。(注意:segue 比按钮点击事件更加有效。)

补充:导航控制器的跳转逻辑

1. 当程序启动的时候,会先进入导航控制器的根控制器。这个时候导航控制器当中的控制器栈就会将根控制器压入进去。
2. 每当程序进入一个新的控制器的时候,新控制器就会被压入导航控制器的控制器栈当中。导航控制器栈中元素 +1。
3. 当程序退出当前控制器以后,会将之前的控制器弹出导航控制器栈当中。导航控制器栈中元素 -1。
4. 如果你需要返回的控制器不是直接相关的控制器,则栈会将这里面的在需要弹出来之前的所有控制器全部都弹出来。

补充:导航控制器传值的问题

1. 当往其他控制器传的值是为了设置导航栏或者是底栏的数据的时候,直接传值即可。
2. 当往其他控制器上的控件传值的时候,需要先将值存储在控制器当中的自定义属性上,然后再从 viewDidLoad 方法当中设置(保证控制器的 view 加载完成。因为控制器当中的控件均为懒加载的,只有界面完全加载完成才是创建成功)。
3. 当通过 StoryBoard 传值的时候,需要在目标控制器当中重写 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender; 通过这个方法,可以将上个控制器当中的数据,传递给下一个控制器。

补充:UINavigationController 与 UITabBarController 之间的配合关系

UINavigationController 导航控制器_第1张图片
在这种结构下,UITabBarController 作为最底层的控制器。负责控制 4 个 UINavigationController 的切换。当点击下面的选项的时候,就进入到其中一个 UINavigationController 的 rootViewController。这个是 Apple 推荐的布局方式,因为这样可以保证界面显示和功能的快速切换。
UINavigationController 导航控制器_第2张图片
而在这种结构下,UINavigationController 作为最底层的控制器,他的根控制器为 UITabBarController。UITabBarController 管理着其他控制器的切换,当在 UITabBar 当中选中一个控制器,控制器当中点击一个按钮进入新控制器的时候,下面的 UITabBar 就会一起同时被移动走。现在常用的社交类 App 都是用这种控制器管理模式。
参考链接:UINavigationController使用心得 - 简书
参考图片:https://github.com/geektime-geekbang/geektime-ios-course/blob/master/Doc/极客时间《从0开发一款iOS应用》课件.pdf

你可能感兴趣的:(iOS开发)