UINavigationController这一篇就够了

zhaobin545 7年前
   <h2>(一)UINavigationController及其相关控件之间的关系</h2>    <pre>  <code class="language-objectivec">@interface UINavigationController : UIViewController  @property(nonatomic,readonly) UINavigationBar *navigationBar;    @interface UIViewController (UINavigationControllerItem)  @property(nonatomic,readonly,strong) UINavigationItem *navigationItem;    @interface UINavigationBar : UIView  @property(nullable, nonatomic,readonly,strong) UINavigationItem *topItem;  @property(nullable, nonatomic,readonly,strong) UINavigationItem *backItem;  @property(nullable,nonatomic,copy) NSArray<UINavigationItem *> *items;    @interface UINavigationItem : NSObject  @property(nullable,nonatomic,strong) UIBarButtonItem *backBarButtonItem  @property(nullable,nonatomic,copy) NSArray<UIBarButtonItem *> *leftBarButtonItems;  @property(nullable,nonatomic,copy) NSArray<UIBarButtonItem *> *rightBarButtonItems;  @property(nullable, nonatomic,strong) UIBarButtonItem *leftBarButtonItem;  @property(nullable, nonatomic,strong) UIBarButtonItem *rightBarButtonItem;    @interface UIBarButtonItem : UIBarItem  @property(nullable, nonatomic)         SEL                  action;     @interface UIBarItem : NSObject  @property(nullable, nonatomic,copy)             NSString    *title;  @property(nullable, nonatomic,strong)           UIImage     *image;</code></pre>    <p>通过对上述几个类的属性的罗列,我们可以做个总结</p>    <p>基本介绍</p>    <ul>     <li>UIBarItem<br> 一个可以放置在Bar之上的所有小控件类的抽象类,可以设置标题,图片等</li>     <li>UIBarButtonItem<br> 继承UIBarItem,增加了动作以及目标等button的属性。相当于放在UIToolBar或者UINavigationBar上的特殊的button。</li>     <li>UINavigationItem<br> 包含了title,prompt,titleView,leftBarButtonItem,rightBarButtonItem,backBarButonItem等当前页面上所有的信息</li>     <li>UINavigationBar<br> NavigaitonBar就是导航栏 主要对UINavigationItem进行栈管理 展示导航栏的外观背景</li>     <li>UINavigationController<br> 包含了viewcontrollers、navigationbar、toolbar</li>    </ul>    <p>关系综述</p>    <ul>     <li>UINavigationController是一个容器类,对ViewController进行栈管理,包含navigationBar。</li>     <li>UINavigationBar 即UINavigationController顶部的导航栏,主要负责外观背景的展示,并对navigationItem进行栈管理</li>     <li>UINavigationItem是导航栏上显示的具体的元素的一个抽象类,UINavigationController 通过Category的方法为ViewController添加了一个navigationItem,把UINavigationItem交由ViewController管理 <p>// Created on-demand so that a view controller may customize its navigation appearance.</p> </li>    </ul>    <p>这里引用 叶落寒 的一段介绍,更加的通俗易懂</p>    <p>通俗地说就是,UINavigationController是个容器,里面可以装很多UIViewController。装这么多UIViewController让用户怎么控制它们呢?总得有个工具吧,这个工具就是UINavigationBar。一个容器就这么一个bar,相当于控制台吧。但是管理那么多UIViewController,控制台上得按钮啊、标题啊,都千篇一律是不是看起来太无聊了。为了解决这个问题,UINavigationController为每个UIViewController生成一个UINavigationItem,通过这个UINavigationItem可以改变控制台“上面”的按钮和标题。如果你不自定义UINavigationItem,UINavigationController会使用默认的;</p>    <h2>(二)UINavigationController及其相关控件的属性和方法</h2>    <h3>1. UIBarButtonItem</h3>    <pre>  <code class="language-objectivec">//初始化方法  - (instancetype)init;  - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder;  - (instancetype)initWithImage:(nullable UIImage *)image landscapeImagePhone:(nullable     UIImage *)landscapeImagePhone style:(UIBarButtonItemStyle)style target:(nullable id)target action:(nullable SEL)action;  - (instancetype)initWithTitle:(nullable NSString *)title style:(UIBarButtonItemStyle)style target:(nullable id)target action:(nullable SEL)action;  - (instancetype)initWithBarButtonSystemItem:(UIBarButtonSystemItem)systemItem target:(nullable id)target action:(nullable SEL)action;  - (instancetype)initWithCustomView:(UIView *)customView;    @property(nonatomic)         UIBarButtonItemStyle style;  //类型  @property(nonatomic)         CGFloat              width;  @property(nullable, nonatomic,copy)    NSSet<NSString *>   *possibleTitles;  @property(nullable, nonatomic,strong)  __kindof UIView     *customView;  @property(nullable, nonatomic)         SEL                  action;  @property(nullable, nonatomic,weak)    id                   target;  @property(nullable, nonatomic,strong) UIColor *tintColor    //为任意style的button设置背景图片  - (void)setBackgroundImage:(nullable UIImage *)backgroundImage forState:(UIControlState)state barMetrics:(UIBarMetrics)barMetrics  - (nullable UIImage *)backgroundImageForState:(UIControlState)state barMetrics:(UIBarMetrics)barMetrics    //为特定style的button设置背景图片  - (void)setBackgroundImage:(nullable UIImage *)backgroundImage forState:(UIControlState)state style:(UIBarButtonItemStyle)style barMetrics:(UIBarMetrics)barMetrics  - (nullable UIImage *)backgroundImageForState:(UIControlState)state style:(UIBarButtonItemStyle)style barMetrics:(UIBarMetrics)barMetrics      //设置背景图片垂直方向的偏移量  - (void)setBackgroundVerticalPositionAdjustment:(CGFloat)adjustment forBarMetrics:(UIBarMetrics)barMetrics  - (CGFloat)backgroundVerticalPositionAdjustmentForBarMetrics:(UIBarMetrics)barMetrics    //设置标题的偏移量  - (void)setTitlePositionAdjustment:(UIOffset)adjustment forBarMetrics:(UIBarMetrics)barMetrics  - (nullable UIImage *)backButtonBackgroundImageForState:(UIControlState)state barMetrics:(UIBarMetrics)barMetrics    //设置返回按钮标题偏移量  - (void)setBackButtonTitlePositionAdjustment:(UIOffset)adjustment forBarMetrics:(UIBarMetrics)barMetrics  - (UIOffset)backButtonTitlePositionAdjustmentForBarMetrics:(UIBarMetrics)barMetrics    //设置返回按钮背景图片在垂直方向上的偏移量  - (void)setBackButtonBackgroundVerticalPositionAdjustment:(CGFloat)adjustment forBarMetrics:(UIBarMetrics)barMetrics  - (CGFloat)backButtonBackgroundVerticalPositionAdjustmentForBarMetrics:(UIBarMetrics)barMetrics</code></pre>    <pre>  <code class="language-objectivec">typedef NS_ENUM(NSInteger, UIBarButtonSystemItem) {      UIBarButtonSystemItemDone,//显示完成      UIBarButtonSystemItemCancel,//显示取消      UIBarButtonSystemItemEdit,  //显示编辑      UIBarButtonSystemItemSave, //显示保存       UIBarButtonSystemItemAdd,//显示加号      UIBarButtonSystemItemFlexibleSpace,//什么都不显示,占位一个空间位置      UIBarButtonSystemItemFixedSpace,//和上一个类似      UIBarButtonSystemItemCompose,//显示写入按钮      UIBarButtonSystemItemReply,//显示循环按钮      UIBarButtonSystemItemAction,//显示活动按钮      UIBarButtonSystemItemOrganize,//显示组合按钮      UIBarButtonSystemItemBookmarks,//显示图书按钮      UIBarButtonSystemItemSearch,//显示查找按钮      UIBarButtonSystemItemRefresh,//显示刷新按钮      UIBarButtonSystemItemStop,//显示停止按钮      UIBarButtonSystemItemCamera,//显示相机按钮      UIBarButtonSystemItemTrash,//显示移除按钮      UIBarButtonSystemItemPlay,//显示播放按钮      UIBarButtonSystemItemPause,//显示暂停按钮      UIBarButtonSystemItemRewind,//显示退后按钮      UIBarButtonSystemItemFastForward,//显示前进按钮      UIBarButtonSystemItemUndo,//显示消除按钮      UIBarButtonSystemItemRedo ,//显示重做按钮      UIBarButtonSystemItemPageCurl ,//在tool上有效  };</code></pre>    <h3>2.UINavigationItem</h3>    <pre>  <code class="language-objectivec">NS_CLASS_AVAILABLE_IOS(2_0) @interface UINavigationItem : NSObject <NSCoding>  //初始化  - (instancetype)initWithTitle:(NSString *)title NS_DESIGNATED_INITIALIZER;  - (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;    //设置导航栏中间的内容标题  @property(nullable, nonatomic,copy)   NSString        *title;           //设置导航栏中间的内容视图      @property(nullable, nonatomic,strong) UIView          *titleView;          //提示  @property(nullable,nonatomic,copy)   NSString *prompt;        //返回  @property(nullable,nonatomic,strong) UIBarButtonItem *backBarButtonItem;   //是否隐藏返回Button  @property(nonatomic,assign) BOOL hidesBackButton;  - (void)setHidesBackButton:(BOOL)hidesBackButton animated:(BOOL)animated;    //左边数组Item  @property(nullable,nonatomic,copy) NSArray<UIBarButtonItem *> *leftBarButtonItems NS_AVAILABLE_IOS(5_0);  //右边数组Item  @property(nullable,nonatomic,copy) NSArray<UIBarButtonItem *> *rightBarButtonItems NS_AVAILABLE_IOS(5_0);  - (void)setLeftBarButtonItems:(nullable NSArray<UIBarButtonItem *> *)items animated:(BOOL)animated NS_AVAILABLE_IOS(5_0);  - (void)setRightBarButtonItems:(nullable NSArray<UIBarButtonItem *> *)items animated:(BOOL)animated NS_AVAILABLE_IOS(5_0);    //通过指定该属性为YES,可以让leftBarButtonItem和backBarButtonItem同时显示,其中leftBarButtonItem显示在backBarButtonItem的右边 默认值为NO  @property(nonatomic) BOOL leftItemsSupplementBackButton NS_AVAILABLE_IOS(5_0);    //左边Item  @property(nullable, nonatomic,strong) UIBarButtonItem *leftBarButtonItem;  //右边Item  @property(nullable, nonatomic,strong) UIBarButtonItem *rightBarButtonItem;  - (void)setLeftBarButtonItem:(nullable UIBarButtonItem *)item animated:(BOOL)animated;  - (void)setRightBarButtonItem:(nullable UIBarButtonItem *)item animated:(BOOL)animated;  @end</code></pre>    <p>prompt 是一个NSString类型描述,注意添加该描述以后NavigationBar的高度会增加30,总的高度会变成74(不管当前方向是Portrait还是Landscape,此模式下navgationbar都使用高度44加上prompt30的方式进行显示)。</p>    <p>如:</p>    <pre>  <code class="language-objectivec">self.navigationItem.prompt=@"这是什么?";  self.title=@"HAH";</code></pre>    <p style="text-align:center"><img src="https://simg.open-open.com/show/ff7a6fab5861aaa4d0e570e799fe7caa.png"></p>    <p>prompt.png</p>    <h3>3.UINavigationBar</h3>    <pre>  <code class="language-objectivec">NS_CLASS_AVAILABLE_IOS(2_0) @interface UINavigationBar : UIView <NSCoding, UIBarPositioning>     //UIBarStyleDefault  灰色背景 白色文字 UIBarStyleBlack    纯黑色背景 白色文字  @property(nonatomic,assign) UIBarStyle barStyle;  @property(nullable,nonatomic,weak) id<UINavigationBarDelegate> delegate;  //Translucent设置成透明度,设置成YES会有一种模糊效果  @property(nonatomic,assign,getter=isTranslucent) BOOL translucent NS_AVAILABLE_IOS(3_0) UI_APPEARANCE_SELECTOR;   //UINavigationBar上面不只是简单的显示标题,它也将标题进行了堆栈的管理,每一个标题抽象为的对象在iOS系统中是UINavigationItem对象,我们可以通过push与pop操作管理item组。  //向栈中添加一个item,上一个item会被推向导航栏的左侧,变为pop按钮,会有一个动画效果  - (void)pushNavigationItem:(UINavigationItem *)item animated:(BOOL)animated;  //pop一个item  - (nullable UINavigationItem *)popNavigationItemAnimated:(BOOL)animated;   //当前push到最上层的item  @property(nullable, nonatomic,readonly,strong) UINavigationItem *topItem;  //仅次于最上层的item,一般式被推向导航栏左侧的item  @property(nullable, nonatomic,readonly,strong) UINavigationItem *backItem;  //获取堆栈中所有item的数组  @property(nullable,nonatomic,copy) NSArray<UINavigationItem *> *items;  //设置一组item  - (void)setItems:(nullable NSArray<UINavigationItem *> *)items animated:(BOOL)animated;     //系统类型按钮文字颜色  @property(null_resettable, nonatomic,strong) UIColor *tintColor;    //通过barTintColor来设置背景色  @property(nullable, nonatomic,strong) UIColor *barTintColor NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR;      //设置工具栏背景和阴影图案  - (void)setBackgroundImage:(nullable UIImage *)backgroundImage forBarPosition:(UIBarPosition)barPosition barMetrics:(UIBarMetrics)barMetrics NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR;  - (nullable UIImage *)backgroundImageForBarPosition:(UIBarPosition)barPosition barMetrics:(UIBarMetrics)barMetrics NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR;    //通过背景图片来设置导航栏的外观  - (void)setBackgroundImage:(nullable UIImage *)backgroundImage forBarMetrics:(UIBarMetrics)barMetrics NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;  - (nullable UIImage *)backgroundImageForBarMetrics:(UIBarMetrics)barMetrics NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;    //背景阴影图片 - 即分割线  @property(nullable, nonatomic,strong) UIImage *shadowImage NS_AVAILABLE_IOS(6_0) UI_APPEARANCE_SELECTOR;    //标题的富文本  @property(nullable,nonatomic,copy) NSDictionary<NSString *,id> *titleTextAttributes NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;    //标题垂直偏移  - (void)setTitleVerticalPositionAdjustment:(CGFloat)adjustment forBarMetrics:(UIBarMetrics)barMetrics NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;  - (CGFloat)titleVerticalPositionAdjustmentForBarMetrics:(UIBarMetrics)barMetrics NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;    //设置返回按钮的图片  @property(nullable,nonatomic,strong) UIImage *backIndicatorImage NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR;  @property(nullable,nonatomic,strong) UIImage *backIndicatorTransitionMaskImage NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR;  @end</code></pre>    <h3>4.UINavigationController</h3>    <pre>  <code class="language-objectivec">NS_CLASS_AVAILABLE_IOS(2_0) @interface UINavigationController : UIViewController    //UINavigationController初始化,自定义NavigationBar,自定义toolbar  - (instancetype)initWithNavigationBarClass:(nullable Class)navigationBarClass toolbarClass:(nullable Class)toolbarClass NS_AVAILABLE_IOS(5_0);    //UINavigationController初始化,导航控制器的根控制器  - (instancetype)initWithRootViewController:(UIViewController *)rootViewController;    //压栈:将目标控制器压入栈中  - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated;     //弹栈:将栈顶控制器从栈中弹出  - (nullable UIViewController *)popViewControllerAnimated:(BOOL)animated;    //弹栈:弹到指定的目标控制器  - (nullable NSArray<__kindof UIViewController *> *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated;     //弹栈:弹到根控制器  - (nullable NSArray<__kindof UIViewController *> *)popToRootViewControllerAnimated:(BOOL)animated;  //导航栈的栈顶视图 只读 就是某个导航栈的栈顶视图,和导航息息相关  @property(nullable, nonatomic,readonly,strong) UIViewController *topViewController;   //当前显示的控制器 只读 visibleViewController和哪个导航栈没有关系,只是当前显示的控制器,也就是说任意一个导航的visibleViewController所返回的值应该是一样的  @property(nullable, nonatomic,readonly,strong) UIViewController *visibleViewController;    //栈里的视图控制器数组  @property(nonatomic,copy) NSArray<__kindof UIViewController *> *viewControllers;    //替换栈中的视图控制器数组  - (void)setViewControllers:(NSArray<UIViewController *> *)viewControllers animated:(BOOL)animated NS_AVAILABLE_IOS(3_0);     //是否隐藏导航栏  @property(nonatomic,getter=isNavigationBarHidden) BOOL navigationBarHidden;    //设置导航栏隐藏 是否有动画  - (void)setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated;     //导航栏  @property(nonatomic,readonly) UINavigationBar *navigationBar;     //toolbar是否隐藏  @property(nonatomic,getter=isToolbarHidden) BOOL toolbarHidden NS_AVAILABLE_IOS(3_0);    //toolbar是否隐藏 是否有动画  - (void)setToolbarHidden:(BOOL)hidden animated:(BOOL)animated NS_AVAILABLE_IOS(3_0);     //toolbar对象  @property(null_resettable,nonatomic,readonly) UIToolbar *toolbar NS_AVAILABLE_IOS(3_0);     //委托  @property(nullable, nonatomic, weak) id<UINavigationControllerDelegate> delegate;    //边缘侧滑返回手势  @property(nullable, nonatomic, readonly) UIGestureRecognizer *interactivePopGestureRecognizer NS_AVAILABLE_IOS(7_0);    //展示视图控制器  - (void)showViewController:(UIViewController *)vc sender:(nullable id)sender NS_AVAILABLE_IOS(8_0); // Interpreted as pushViewController:animated:    //输入键盘出现时将导航栏隐藏 IOS8特性  @property (nonatomic, readwrite, assign) BOOL hidesBarsWhenKeyboardAppears NS_AVAILABLE_IOS(8_0);    //滚动页面时隐藏Bar  IOS8特性  @property (nonatomic, readwrite, assign) BOOL hidesBarsOnSwipe NS_AVAILABLE_IOS(8_0);    //获取能够隐藏navigationBar的滑动手势 只读  @property (nonatomic, readonly, strong) UIPanGestureRecognizer *barHideOnSwipeGestureRecognizer NS_AVAILABLE_IOS(8_0);    //当设置为true时,横向方向时隐藏NavigationBar  @property (nonatomic, readwrite, assign) BOOL hidesBarsWhenVerticallyCompact NS_AVAILABLE_IOS(8_0);    //当设置为true时,如果有没处理的点击手势就会隐藏和现实navigationBar   @property (nonatomic, readwrite, assign) BOOL hidesBarsOnTap NS_AVAILABLE_IOS(8_0);    //获取能够隐藏navigationBar的点击手势 只读  @property (nonatomic, readonly, assign) UITapGestureRecognizer *barHideOnTapGestureRecognizer NS_AVAILABLE_IOS(8_0);    @end</code></pre>    <pre>  <code class="language-objectivec">@interface UIViewController (UINavigationControllerItem)  //导航栏上面用户自定义视图  @property(nonatomic,readonly,strong) UINavigationItem *navigationItem;   //推送时隐藏bottom  @property(nonatomic) BOOL hidesBottomBarWhenPushed;  //下级视图的导航控制器  @property(nullable, nonatomic,readonly,strong) UINavigationController *navigationController;   @end</code></pre>    <pre>  <code class="language-objectivec">@interface UIViewController (UINavigationControllerContextualToolbarItems)  //属性设置工具条中包含的按钮  @property (nullable, nonatomic, strong) NSArray<__kindof UIBarButtonItem *> *toolbarItems NS_AVAILABLE_IOS(3_0);  - (void)setToolbarItems:(nullable NSArray<UIBarButtonItem *> *)toolbarItems animated:(BOOL)animated NS_AVAILABLE_IOS(3_0);  @end</code></pre>    <h2>(三)实际开发过程中的一些问题</h2>    <h3>1.UINavigationBar的背景颜色</h3>    <pre>  <code class="language-objectivec">-(void)changeNavigationBarBackgroundColor {      //背景色      self.navigationBar.barTintColor = [UIColor blueColor];        //title字体      //[self.navigationController.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor lightGrayColor],NSFontAttributeName:[UIFont systemFontOfSize:17]}];        //修改UIBarButtonItem 图片 title颜色      self.navigationBar.tintColor = [UIColor greenColor];        //是否半透明 当为YES时 设置的导航栏背景颜色会和实际rgb值有误差      self.navigationBar.translucent = NO;        //如果想要半透明效果 颜色没有色差 可以通过设置背景图片的方法 背景图片会覆盖barTintColor      //- (void)setBackgroundImage:(nullable UIImage *)backgroundImage forBarMetrics:(UIBarMetrics)barMetrics  }</code></pre>    <h3>2.UINavigationBar底部的shadowImage</h3>    <p>Apple官方对shadowImage有这样的介绍:</p>    <p>/ <em>Default is nil. When non-nil, a custom shadow image to show instead of the default shadow image. For a custom shadow to be shown, a custom background image must also be set with -setBackgroundImage:forBarMetrics: (if the default background image is used, the default shadow image will be used).</em> /</p>    <p>设置shadowImage必须先setBackgroundImage,否则无法实现效果</p>    <pre>  <code class="language-objectivec">-(void)changeNavigationBarBottonLine {      //设置底部line颜色时需要同时设置backgroundImage即导航栏的背景图片 否则没有效果      [self.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];      [self.navigationBar setShadowImage:[self imageWithColor:[UIColor redColor]]];      //此处设置透明颜色的image,底部line即可隐藏,但此种方法隐藏,没有办法再显示 下面方法通过找到该view 控制其hidden属性      //[self reducibilityHiddenNavogationBarLine];  }</code></pre>    <p>找到该imageView设置起Hidden为YES</p>    <pre>  <code class="language-objectivec">-(void)reducibilityHiddenNavogationBarLine {      UIImageView * imageView = [self findLineImageViewUnder:self.navigationBar];      if (imageView) {         imageView.hidden = YES;      }  }</code></pre>    <p>找到该imageView</p>    <pre>  <code class="language-objectivec">-(UIImageView *)findLineImageViewUnder:(UIView *)view {      if ([view isKindOfClass:[UIImageView class]] && view.bounds.size.height <= 1.0) {          return (UIImageView *)view;      }      for (UIView * subView in view.subviews) {          UIImageView * imageView = [self findLineImageViewUnder:subView];          if (imageView) {              return imageView;          }      }      return nil;  }</code></pre>    <h3>3.自定义导航栏的返回按钮</h3>    <pre>  <code class="language-objectivec">@property(nonatomic,readonly) UINavigationBar *navigationBar;// The navigation bar managed by the controller. Pushing, popping or setting navigation items on a managed navigation bar is not supported.</code></pre>    <p>受controller管理的navigationBar 不支持对navigation items操作,所以此处对返回按钮的操作是在ViewController完成的,以下代码中self表示ViewController</p>    <p>Apple官方对setBackIndicatorImage和setBackIndicatorTransitionMaskImage做了如下解释,必须同时设置才能生效</p>    <pre>  <code class="language-objectivec">/*   The back indicator image is shown beside the back button.   The back indicator transition mask image is used as a mask for content during push and pop transitions   Note: These properties must both be set if you want to customize the back indicator image.   */</code></pre>    <p>1.自定义文字+图片</p>    <pre>  <code class="language-objectivec">-(void)createCustomBackBarItem {        //修改图片文字颜色      self.navigationController.navigationBar.tintColor = [UIColor whiteColor];        //替换图片      [self.navigationController.navigationBar setBackIndicatorImage:[UIImage imageNamed:@"erwema"]];      [self.navigationController.navigationBar setBackIndicatorTransitionMaskImage:[UIImage imageNamed:@"erwema"]];        //设置文字      UIBarButtonItem * backBarItem = [[UIBarButtonItem alloc]initWithTitle:@"返回" style:UIBarButtonItemStylePlain target:nil action:nil];      self.navigationItem.backBarButtonItem = backBarItem;  }</code></pre>    <p>注意:</p>    <p>对backBarButtonItem的修改是在当前viewController前一个页面完成的,在当前页面修改针对下一个viewController的navigationItem生效</p>    <p>2.不显示文字</p>    <p>设置Title在Y方向上的偏移量,使其移除屏幕,该方法在第一次进入时会有个文字移动的动画效果,效果不好,不推荐使用</p>    <pre>  <code class="language-objectivec">[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -100) forBarMetrics:UIBarMetricsDefault];</code></pre>    <p>3.使用leftBarButtonItem替代backBarButtonItem</p>    <p>使用这种方法,不能使用边缘滑动返回手势,且不能同时设置图片和标题</p>    <pre>  <code class="language-objectivec">-(void)setLeftBarItemBack  {      UIBarButtonItem *leftBarBtnItem = [[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:@"back"] style:UIBarButtonItemStylePlain target:self action:@selector(clickLeftBarBtnItem:)];      [self.navigationItem setLeftBarButtonItem:leftBarBtnItem animated:YES];      self.navigationItem.leftBarButtonItem.tintColor = NavigationLeftBackColor;  }    /**   *  导航条leftBarBtn事件   */  - (void)clickLeftBarBtnItem:(UIBarButtonItem *)sender {      [self.navigationController popViewControllerAnimated:YES];  }</code></pre>    <p>4.使用CustomView的方法</p>    <p>此方法不适于backBarButtonItem,只能用于leftBarButtonItem</p>    <p>注意:</p>    <p>1.如果B视图有一个自定义的左侧按钮(leftBarButtonItem),则会显示这个自定义按钮;</p>    <p>2.如果B没有自定义按钮,但是A视图的backBarButtonItem属性有自定义项,则显示这个自定义项;</p>    <p>3.如果前2条都没有,则默认显示一个后退按钮,后退按钮的标题是A视图的标题;</p>    <p>此处注意:</p>    <p>5.0中新增加了一个属性leftItemsSupplementBackButton,通过指定该属性为YES,可以让leftBarButtonItem和backBarButtonItem同时显示,其中leftBarButtonItem显示在backBarButtonItem的右边。</p>    <p>使用3、4方法,边缘返回会失效,此时加上这句代码依然可以实现边缘滑动返回</p>    <pre>  <code class="language-objectivec">self.navigationController.interactivePopGestureRecognizer.delegate = self;</code></pre>    <p>这里推荐使用 <a href="/misc/goto?guid=4959635476022877280" rel="nofollow,noindex">FDFullscreenPopGesture</a> 全屏滑动手势返回,减少工作量。</p>    <h3>4.navigationBar偶尔显示上一个页面的navigationBar</h3>    <p>一般情况下都是正常的。但是在偶然情况下,会出现在进入新界面后,新界面的navigationBar会突然消失,出现的还是上一个界面的 navigationBar。从此以后,navigationBar 全乱了, kill 掉重新进,恢复正常。</p>    <p>原因:</p>    <p>一般我们会打点调用navigationBarHidden的属性来设置导航栏是否隐藏,这种方法是不带动画效果的。这样偶尔就会导致错乱,这应该是一个系统的bug,所以应尽量使用</p>    <pre>  <code class="language-objectivec">[self.navigationController setNavigationBarHidden:YES animated:YES];</code></pre>    <p>来设置navigationBar的Hidden属性。</p>    <h3>5.修改系统navigationBar的高度</h3>    <pre>  <code class="language-objectivec">UINavigationBar * navigatioBar = self.navigationController.navigationBar;  CGFloat navBarHeight = 100.f;  CGRect frame = CGRectMake(0.0f, 0.0f, 320.0f, navBarHeight);  [navigatioBar setFrame:frame];</code></pre>    <p>此种方法经测试只有在非rootViewController中才能生效,这样在第一次进入根视图的时候navigationBar并不会变高,不知有没有人知道该如何解决,欢迎赐教。</p>    <h3>6.易混淆知识点</h3>    <p>1.self.title、self.navigationItem.title、self.tabBarItem.title之间的关系</p>    <p>一目了然</p>    <pre>  <code class="language-objectivec">self.navigationItem.title = @"my title"; //sets navigation bar title.  self.tabBarItem.title = @"my title"; //sets tab bar title.  self.title = @"my title"; //sets both of these.</code></pre>    <ol>     <li>如果当前VC通过 self.navigationItem.titleView指定了自定义的titleView,系统将会显示指定的titleView,设置self.title、self.navigationItem.title不会改变导航栏的标题。</li>     <li>如果当前VC没有指定titleView,系统则会根据当前VC的title或者当前VC的navigationItem.title的内容创建一个UILabel并显示。</li>     <li>self.title会重写navigationItem和tabBarItem的title。</li>    </ol>    <p>2.self.navigationItem,self.navigationController.navigationItem的关系</p>    <p>navigationItem是UIViewController的一个属性,navigationController继承UIViewController,自然会继承viewControoler的navigationItem属性。此处self.navigationController.navigationItem是应该被忽视的。navigationItem直接由viewController管理。</p>    <p>3.UIBarMetrics和UIBarPosition</p>    <pre>  <code class="language-objectivec">typedef NS_ENUM(NSInteger, UIBarMetrics) {      UIBarMetricsDefault, //横屏      UIBarMetricsCompact,//竖屏      UIBarMetricsDefaultPrompt = 101, //横屏且设置了prompt属性  Applicable only in bars with the prompt property, such as UINavigationBar and UISearchBar      UIBarMetricsCompactPrompt, //竖屏且设置了prompt属性  };    typedef NS_ENUM(NSInteger, UIBarPosition) {      UIBarPositionAny = 0, //Bar在任何位置      UIBarPositionBottom = 1, //Bar在底部      UIBarPositionTop = 2, //Bar在顶部      UIBarPositionTopAttached = 3, //Bar在顶部,且他的背景扩展到statusBar的区域  } NS_ENUM_AVAILABLE_IOS(7_0);</code></pre>    <p>不正之处,还望多多指教!</p>    <p>参考文章</p>    <p><a href="/misc/goto?guid=4959738041375763830" rel="nofollow,noindex">你真的了解UINavigationController吗?</a></p>    <p><a href="/misc/goto?guid=4959738041465447592" rel="nofollow,noindex">UINavigationItem UINavigationBar 关系分析</a></p>    <p> </p>    <p>来自:http://www.jianshu.com/p/69b4e7bed7d4</p>    <p> </p>