UINavigationController结构

导航条层次结构
UINavigationController –(1:1)–> UINavigationBar –(1:多)–> UINavigationItem –(1:多)–> UIBarButtonItem –(1:1)–> CustomView
其中UINavigationBar是UIView的子类,UINavigationItem和UIBarButtonItem都是NSObject的子类,也就是说UINavigationItem和UIBarButtonItem都是 UINavigationBar用于显示的model数据。

UINavigationBar与UINavigationItem
UINavigationBar与UINavigationItem是一对多的关系,UINavigationItem存放UINavigationBar用于显示的数据(title, UIBarButtonItem等)。
UINavigationBar提供 push和pop UINavigationItem的方法,push UINavigationItem后UINavigationBar显示样式对应于新push的UINavigationItem,
上一个UINavigationItem显示成当前UINavigationBar样式的返回按钮以表示回到上一个UINavigationItem。pop 操作与push操作相反,不再赘述。
下面是UINavigationBar中相关的push/pop UINavigationItem的方法:
- (void)pushNavigationItem:(UINavigationItem *)item animated:(BOOL)animated;
- (UINavigationItem *)popNavigationItemAnimated:(BOOL)animated; // Returns the item that was popped.

如果你尝试在UINavigationController的UINavigationBar上push或pop UINavigationItem,那么程序会crash,如下:
"Cannot call pushNavigationItem:animated: directly on a UINavigationBar managed by a controller."
说明UINavigationController自己管理的UINavigationBar不让程序员手动去push和pop UINavigationItem。

试想一下,如果程序员自己实例化一个UINavigationBar,再在其上push和pop UINavigationItem,这样就不会crash了吧?
没错, 是这样的,如下:
- (void)viewDidLoad {
    __navigationBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];   //设置导航栏界面
    UINavigationItem *navigationItem = [[UINavigationItem alloc] initWithTitle:@"登录"];  //初始化并设置title
    UIBarButtonItem *rightBarbutton = [[UIBarButtonItem alloc] initWithTitle:@"注册" style:UIBarButtonItemStyleBordered target:self action:@selector(signin)];
    navigationItem.rightBarButtonItem = rightBarbutton;
    [navigationBar pushNavigationItem:navigationItem animated:YES];
    [self.view __navigationBar];
}

- (void)signin {
    UINavigationItem *navigationItem = [[UINavigationItem alloc] initWithTitle:@"注册"];  //初始化并设置title
    [__navigationBar pushNavigationItem:navigationItem animated:YES];
}
运行的效果和我们采用UINavigationController push和pop的效果一样,只是没有了UIViewController参与。

再试想一下,如果程序员自己来实现UINavigatioinController,那么上面这个利用UINavigationBar push UINavigationItem的环节肯定少不了,
只是另外还要管理UINavigationItem与UIViewController的对应关系、UIViewController类似于UINavigationItem的push/pop、UIViewController stack中每一个的生命周期。
UINavigationController与UIViewController与UINavigationItem
从上一点的分析中已经能大致推测出UINavigationController里肯定有一个UINavigationBar,查看UINavigationController的.h文件也证实了这一点,
所以UINavigationController push/pop UIViewController时,肯定会管理UINavigationItem在UINavigationBar上的pop/push。

那么UINavigationController里管理的UINavigationItem从哪里来呢,以及UIViewController与UINavigationItem的对应关系是怎么样的呢?
    通过查看UIViewControlelr以及UIViewController (UINavigationControllerItem),可以知道
    UIViewControlelr它有一个叫_navigationItem的实例变量,UIViewController (UINavigationControllerItem)中扩展了一个navigationItem属性,
    应该就是访问_navigationItem实例变量。所以,不难推测出UINavigationController push UIViewController时
    UIViewController的View会被用于显示,UIViewController的UINavigationItem会被对应于UINavigationBar的显示,
    并且UINavigationItem被放到UINavigationBar中管理。

UINavigationController也提供了类似于UINavigationBar push/pop的方法,如下:
// Uses a horizontal slide transition. Has no effect if the view controller is already in the stack.
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated;
// Returns the popped controller.
- (UIViewController *)popViewControllerAnimated:(BOOL)animated;
导航条的定制
- (instancetype)initWithNavigationBarClass:(Class)navigationBarClass toolbarClass:(Class)toolbarClass NS_AVAILABLE_IOS(5_0);
UIBarButtonItem定制
- (id)initWithCustomView:(UIView *)customView;
子ViewController层次结构
UINavigationController -(1:多)-> UIViewController -(1:1)->UINavigationItem

子view controller stack的管理

待续。。。

子view controller的生命周期和内存的管理

待续。。。