iOS--UINavigationController学习笔记

来源:互联网 发布:上海婚纱摄影推荐知乎 编辑:程序博客网 时间:2024/06/01 21:43
1.简介
        UINavigationController:是iOS常见的一种容器型Controller。官方文档上给出的注释如下
 UINavigationController manages a stack of view controllers and a navigation bar.It performs horizontal view transitions for pushed and popped views while keeping the navigation bar in sync.Most clients will not need to subclass UINavigationController.If a navigation controller is nested in a tabbar controller, it uses the title and toolbar attributes of the bottom view controller on the stack.UINavigationController is rotatable if its top view controller is rotatable.Navigation between controllers with non-uniform rotatability is currently not supported.
意思是说,UINavigationController管理着一个viewController的栈和一个navigation bar(navigation bar后面会说)。管理着出于同一层次的viewController的view,包括压栈和出栈(viewController显示滑进和隐藏滑出界)的转场动画,同时还同步管理着顶部navigation bar的状态。大部分的app都不需要实现一个它的子类(对于一般的功能,都具有支持)。如果一个UINavigationController的实例嵌套在一个UITabbarController的实例中,它将使用栈底的viewController的标题和toolbar的属性。UINavigationController的可旋转是和栈顶的viewController保持一致的。现在还不支持同一层次的viewController旋转类型不一致的压栈出栈。

2.常见属性和方法
- (instancetype)initWithRootViewController:(UIViewController *)rootViewController; 
以一个viewController为栈底,实例化一个navigation viewcontroller

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated; 
展示一个viewcontroller,压栈操作(可以有动画效果)。

- (nullableUIViewController *)popViewControllerAnimated:(BOOL)animated; 
结束并隐藏一个viewcontroller(dealloc),出栈操作(可以有动画效果),返回出栈的viewcontroller

- (nullableNSArray<__kindofUIViewController *> *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated; 
结束并隐藏 在栈中位于一个特殊的viewcontroller之前所有的viewcontroller,并返回

- (nullableNSArray<__kindofUIViewController *> *)popToRootViewControllerAnimated:(BOOL)animated;
出栈到根viewcontroller

@property(nullable,nonatomic,readonly,strong) UIViewController *topViewController; 
栈顶viewcontroller

@property(nullable,nonatomic,readonly,strong) UIViewController *visibleViewController; 
如果模态viewcontroller存在,返回模态viewcontroller,否则栈顶viewcontroller

@property(nonatomic,copy) NSArray<__kindofUIViewController *> *viewControllers; 
当前栈中的元素

- (void)setViewControllers:(NSArray<UIViewController *> *)viewControllers animated:(BOOL)animated NS_AVAILABLE_IOS(3_0); 
设置栈中的元素,animated=yes,根据当前的栈顶viewcontroller在不在这个viewcontroller数组中,模拟一次push和pop的动画。这就相当于对当前的栈进行了一次整体的刷新

下面的bar属性主要是用来显示顶部的导航栏以及底部的工具栏
@property(nonatomic,getter=isNavigationBarHidden)BOOLnavigationBarHidden;
- (void)setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated; 
@property(nonatomic,readonly) UINavigationBar *navigationBar; 
@property(nonatomic,getter=isToolbarHidden)BOOLtoolbarHidden NS_AVAILABLE_IOS(3_0) __TVOS_PROHIBITED;
- (void)setToolbarHidden:(BOOL)hidden animated:(BOOL)animated NS_AVAILABLE_IOS(3_0) __TVOS_PROHIBITED; 
@property(null_resettable,nonatomic,readonly) UIToolbar *toolbar NS_AVAILABLE_IOS(3_0) __TVOS_PROHIBITED;// 

delegate,可以在压栈出栈操作中,设置一些动画,以及一些额外的操作
@property(nullable,nonatomic,weak)id<UINavigationControllerDelegate> delegate;

这里需要说一下visibleViewController和topViewController:topViewController永远代表着栈顶元素;visibleViewController代表着当前显示的那个vc,这个vc可能是top vc,也有可能是top vc 展示出来的vc。

3.UINavigationBar

3.1. 导航栏属性设置:

       通常我们都会在APPDelegate为整个APP的导航栏做全局性的设置,使用[UINavigationBarappearance]这个方法获得当前的导航栏实例;以及在viewController中对当前页面的导航栏做特殊的设置,使用self.navigationController.navigationBar获得当前的导航栏实例。记住,在viewController中对导航栏的设置,要在这个viewController小时之前还原,否则会覆盖全局的设置,从而影响其他页面的显示。
      barTintColor:设置导航栏的整体背景颜色,包括状态栏的背景颜色。如下:
 [[UINavigationBarappearance]setBarTintColor:[UIColoryellowColor]];运行的效果如下
                   
                   
      tintColor:设置导航栏的按钮的图标和文字颜色(系统提供的),自定义的不在此范围;
 [[UINavigationBarappearance]setTintColor:[UIColorredColor]];运行的效果如下
                   
      barStyle:设置导航栏的整体风格,有UIBarStyleDefault和UIBarStyleBlack两种选择。对应以下两种运行结果,可以看到UIBarStyleBlack会影响状态栏的颜色以及导航栏的标题颜色。(但是已经对标题的字体颜色都已经赋值的,就不受影响了)
                    
                   
     titleTextAttributes:设置导航栏的标题的显示样式,包括UITextAttributeFont - 字体 UITextAttributeTextColor - 文字颜色  UITextAttributeTextShadowColor - 文字阴影颜色    UITextAttributeTextShadowOffset - 偏移用于文本阴影
       [[UINavigationBarappearance]setTitleTextAttributes:[NSDictionarydictionaryWithObjectsAndKeys:
                                                   [UIColorredColor],NSForegroundColorAttributeName,
                                                   [UIFontsystemFontOfSize:18.f],NSFontAttributeName,
                                                  nil]];
                   
    backgroundImage/shadowImage:设置导航栏的背景和阴影图片
    [[UINavigationBarappearance]setBackgroundImage:[UIImageimageNamed:xxx]
                            forBarMetrics:UIBarMetricsDefault];
    [[UINavigationBarappearance]setShadowImage:[UIImageimageNamed:xxx]];
     translucent:BOOL,半透明效果。

        补充点:前面说到也可以在viewController中对UINavigationBar进行属性设置,基本上都会生效。但是,有些情况下会发现,viewController的(UIStatusBarStyle)preferredStatusBarStyle是不起作用的,原因是因为当前的viewController是嵌套在一个UINavigationController的实例中,最多只会调用UINavigationController的preferredStatusBarStyle,除非将导航栏隐藏,才会调用viewController的preferredStatusBarStyle方法。解决办法:在iOS9之前,App的info.plist文件中,添加View controller-based status bar appearance的值为NO,(意识是说让Application的设置优先于viewController的设置),通过[[UIApplication sharedApplication] setStatusBarStyle:]这个方法来进行设置修改statusBar;但是在iOS9之后,该方法会提示过时⚠️,解决办法是将 View controller-based status bar appearance的值设置YES,然后通过navigationBar.barStyle来设置。然而,现在很多应用都是在iOS7做适配的时候,将View controller-based status bar appearance设为NO,(iOS之前,默认值为NO,iOS之后为YES),iOS7和8对此也都处于兼容状态。9之后会出现警告。

3.2. UINavigationItem以及其与UINavigationBar的关系:

      在前面的简介之中,提到UINavigationController管理着一个UIViewController的栈和一个UINavigationBar。其实,一个UINavigationController的实例对应一个UINavigationBar的实例,而一个UINavigationBar的实例同样管理着一个栈,这个栈中的元素就是UINavigationItem。所以,既然一个navigationController对应一个navigationBar,可以推断到UINavigationController的栈和UINavigationBar的栈也是对应的,而两个栈里元素也是一一对应,也就是一个UIViewController的实例也对应着一个UINavigationItem的实例(如果不对应,系统会报异常情况)。在navigationController进行push和pop的同时,navigationBar也在同时做相应的push和pop 。在官方的API中,在UINavigationController.h文件中会有一个UIViewController的一个category,里面定义着一个UINavigationItem的变量。
    

3.3.  定制导航栏内容
     
       定制导航栏一般都是在viewController中进行自我定制navigationItem。
       定制title,使用viewController.title和viewController.navigationItem.title都可以实现导航栏title的定制。补充:设置viewController.title会覆盖viewController.navigationItem.title,设置viewController.navigationItem.title不会覆盖viewController.title。
       有的时候需要将导航栏标题修改为一个我们自己想要的UIView,只要将我们需要的UIView赋值给viewController.navigationItem.titleView。比如一个button,一张图片,一个搜索框等等
       定制left/rightBarButtonItem:在导航栏中,左右两边通常都会有一些button或者需要交互的view。这时候就需要给viewController.navigationItem设置left/rightBarButtonItem,可定制成任意样式。
       在导航栏中,如果本身没有对viewController.navigationItem.leftBarButtonItem进行定制,会优先展示上一个页面的backBarButtonItem;如果上一个页面也没有设置backBarButtonItem,就会展示一个系统的回退按钮和上一个页面的title。 

iOS--UINavigationController学习笔记二
0 0