(刚学计算机的新手请先百度,学习什么是“栈”。本人简单形容:栈就相当于放在一个地上可以装书本的盒子,放进去的顺序为书本1、2、3,拿出来的顺序则为3、2、1)
每个ViewController只有一个NavigationItem属性,默认目的是显示当前视图控制器ViewController的主题(title)。
Xcode文档对NavigationItem是这么解释的(关键词:“NavigationItem”)
The default behavior is to create a navigation item that displays the view controller's title.
UINavigationController、UINavigationBar、UIViewController与UINavigationItem之间的关系:
UINavigationBar定义为UINavigationController的一个属性property:
UINavigationController栈负责生成UINavigationBar栈,但UINavigationBar栈中每个UINavigationItem的入栈出栈由UINavigationController中的每个对应的UIViewController管理(记住每个UIViewController都拥有一个UINavigationItem,默认用于显示当前UIViewController的标题title):
简单讲,全局唯一的UINavigationController栈生成全局唯一的UINavigationBar栈,UINavigationController中的每个UIViewController管理UINavigationBar(UINavigationController栈每个UIViewController将自身的属性:navigationItem压入或弹出UINavigationBar)。
两个栈——UINavigationController栈、UINavigationBar栈,从层次关系上来说,是一一对应的:
上方注释的意思,依个人理解,意思是:UINavigationController中当前活动的视图控制器UIViewController与UINavigationBar栈中当前活动的UINavigationItem一一对应,处于同一层次。
用下图来表示:
顺序一:
顺序二:
(感谢在线画图工具Gliffy Editor:https://www.gliffy.com/go/html5/launch?app=1b5094b0-6042-11e2-bcfd-0800200c9a66#)
====================================================================
我们有时会发现ViewController的self.navigationItem、self.navigationController.navigationItem作用一样,它们之间有区别吗?
首先,self.navigationItem不难理解,代表当前控制器的UINavigationItem;
至于self.navigationController.navigationItem,需要先解释一下,self.navigationController是什么意思——
【苹果开发文档对UIViewController.navigationController属性的解释:】the nearest ancestor in the view controller hierarchy that is
a navigation controller...if the receiver or one of its ancestors is a child of a navigation controller,this property contains the owning
navigation controller.this property is nil if the view controller is not embedded inside a navigation controller.
可以简单理解为:self.navigationController代表访问全局UINavigationController中的当前活动视图(其实就是控制器自己)。如果当前控制器不处在UINavigationController中,则获取不到navigationController属性(值为nil);
概括为——每个UIViewController内部都定义了一个navigationController属性,它代表的是已被压入UINavigationController栈中的当前控制器自身(self)!
如果当前控制器未压入栈,self.navigationController=nil;如果控制器已压入栈,self.navigationController=self
现在就可以解答问题了:self.navigationItem、self.navigationController.navigationItem作用一样,但前提必须是此视图控制器已经压入全局的UINavigationController栈中。所以建议最好使用self.navigationItem,防止因当前视图控制器没有压入栈而调用不到控制器自身的navigationItem属性。
可能有人要问,已经有self指针了,那self.navigationController这种设计不是多次一举吗?本人的看法是,它可以用于判断当前控制器是否已被压入栈,以此做出不同响应,比如使用下方代码:
if(self.navigationController)
{
//属性不为nil
代码1
}
else
{
//属性为nil
代码2(比如提示未入栈警告)
}