版本记录
版本号 | 时间 |
---|---|
V1.0 | 2018.05.01 |
前言
iOS中的视图加载可以有两种方式,一种是通过xib加载,另外一种就是通过纯代码加载。它们各有优点和好处,xib比较直观简单,代码比较灵活但是看着很多很乱,上一家公司主要风格就是用纯代码,这一家用的就是xib用的比较多。这几篇我们就详细的介绍一个xib相关知识。感兴趣的可以看上面写的几篇。
1. xib相关(一) —— 基本知识(一)
2. xib相关(二) —— 文件冲突问题(一)
3. xib相关(三) —— xib右侧标签介绍(一)
4. xib相关(四) —— 连线问题(一)
5. xib相关(五) —— 利用layout进行约束之界面(一)
6. xib相关(六) —— 利用layout进行约束之说明和注意事项(二)
7. xib相关(七) —— Storyboard中的segue (一)
8. xib相关(八) —— Size Classes(一)
9. xib相关(九) —— 几个IB修饰符(一)
10. xib相关(十) —— xib的国际化(一)
11. xib相关(十一) —— xib的高冷用法之修改视图的圆角半径、边框宽度和颜色(一)
12. xib相关(十二) —— UIStackView之基本介绍(一)
13. xib相关(十三) —— UIStackView之枚举UIStackViewDistribution使用(二)
14. xib相关(十四) —— UIStackView之UIStackViewAlignment使用(三)
15. xib相关(十五) —— UIStackView之工程实践(四)
16. xib相关(十六) —— UINib之基本介绍(一)
17. xib相关(十七) —— UINib之Introduction(二)
回顾
上一篇主要讲述了UINib之Introduction,这一篇主要讲述Nib文件。
Nib文件
Nib文件在OS X和iOS应用程序的创建中发挥着重要作用。使用nib文件,您可以使用Xcode以图形方式创建和操作用户界面,而不是通过编程方式。由于您可以立即看到更改的结果,因此可以快速尝试不同的布局和配置。您也可以稍后更改用户界面的许多方面而不用重写任何代码。
对于使用AppKit或UIKit框架构建的应用程序,nib文件具有额外的意义。这两个框架都支持使用nib文件来布局window,view和controls,并将这些项目与应用程序的事件处理代码进行整合。 Xcode与这些框架协同工作,可以帮助您将用户界面的控件连接到项目中响应这些控件的对象。这种集成显着减少了加载nib文件后所需的设置数量,并且可以在以后轻松更改代码和用户界面之间的关系。
注意:虽然可以在不使用nib文件的情况下创建Objective-C应用程序,但这样做非常少见,不推荐使用。 根据您的应用程序,避免nib文件可能需要您替换大量的框架行为才能获得与使用nib文件相同的结果。
Anatomy of a Nib File - 分析一个Nib文件
一个nib文件描述了应用程序用户界面的视觉元素,包括窗口,视图,控件等等。 它还可以描述非可视元素,例如应用程序中用于管理窗口和视图的对象。 最重要的是,一个nib文件完全像在Xcode中配置一样描述这些对象。 在运行时,这些描述用于在应用程序内重新创建对象及其配置。 在运行时加载nib文件时,会得到Xcode文档中对象的精确副本。 nib加载代码实例化对象,对其进行配置,并重新建立您在nib文件中创建的任何对象间连接。
以下部分描述了如何组织AppKit和UIKit框架使用的nib文件,在其中找到的对象的类型以及如何有效地使用这些对象。
1. About Your Interface Objects - 关于你的界面对象
界面对象是您添加到nib文件以实现您的用户界面的内容。在运行时加载nib时,界面对象是由nib加载代码实际实例化的对象。大多数新的nib文件默认至少有一个界面对象,通常是一个窗口或菜单资源,并且您将更多的界面对象作为界面设计的一部分添加到nib文件中。这是nib文件中最常见的对象类型,并且通常是为什么您首先创建nib文件的原因。
除了表示视觉对象(如窗口,视图,控件和菜单)之外,界面对象还可以表示非可视对象。在几乎所有情况下,添加到nib文件的非可视对象都是应用程序用来管理可视对象的额外控制器对象。尽管可以在应用程序中创建这些对象,但将它们添加到nib文件并在其中进行配置通常更方便。 Xcode提供了一个通用对象,您可以在将控制器和其他非可视对象添加到nib文件时专门使用它。它还提供了通常用于管理Cocoa绑定的控制器对象。
2. About the File’s Owner - 关于File’s Owner
一个nib文件中最重要的对象之一是文件的所有者对象。 与界面对象不同,文件的所有者对象是一个占位符对象,在加载nib文件时不会创建该对象。 相反,你在你的代码中创建这个对象,并将它传递给nib加载代码。 这个对象如此重要的原因是它是应用程序代码和nib文件内容之间的主要链接。 更具体地说,它是负责nib文件内容的控制器对象。
在Xcode中,您可以在文件的所有者和您的nib文件中的其他界面对象之间创建连接。 加载nib文件时,nib加载代码将使用您指定的替换对象重新创建这些连接。 这允许您的对象引用nib文件中的对象并自动从界面对象接收消息。
3. About the First Responder - 关于First Responder
在nib文件中,First Responder是一个占位符对象,表示应用程序的动态确定响应链中的第一个对象。由于无法在设计时确定应用程序的响应程序链,因此,First Responder占位符充当需要针对应用程序的响应程序链的任何操作消息的替代目标。Menu Items通常以First Responder占位符为目标。例如,“窗口”菜单中的“最小化”菜单项隐藏了应用程序中的最前面的窗口,而不仅仅是特定的窗口,而Copy菜单项应复制当前选择内容,而不仅仅是选择单个控件或视图。您应用程序中的其他对象也可以定位First Responder。
当您将一个nib文件加载到内存中时,您不需要做任何事情来管理或替换First Responder占位符对象。 AppKit和UIKit框架根据应用程序的当前配置自动设置和维护第一响应者。
有关响应者链及其如何用于在基于AppKit的应用程序中分派事件的更多信息,请参阅Cocoa Event Handling Guide中的 Event Architecture。有关iPhone应用程序中响应者链和处理操作的信息,请参阅Event Handling Guide for iOS
。
4. About the Top-Level Objects - 关于顶层对象
当程序加载一个nib文件时,Cocoa会重新创建您在Xcode中创建的对象的整个图形。该对象图包括在nib文件中找到的所有窗口,视图,控件,单元格,菜单和自定义对象。顶级对象是没有父对象的这些对象的子集。顶级对象通常只包含添加到Nib文件的窗口,菜单栏和自定义控制器对象。 (诸如文件所有者,第一响应者和应用程序之类的对象是占位符对象,不被视为顶级对象。)
通常,您使用文件所有者对象中的outlet来存储对nib文件的顶级对象的引用。但是,如果您不使用outlets,则可以直接从nib加载例程中检索顶层对象。您应始终在某处保留一个指向这些对象的指针,因为您的应用程序在使用它们时负责释放这些对象。有关加载时的nib对象行为的更多信息,请参阅Managing the Lifetimes of Objects from Nib Files。
5. About Image and Sound Resources - 关于图像和声音资源
在Xcode中,您可以从nib文件的内容中引用外部图像和声音资源。某些控件和视图可以显示图像或播放声音作为其默认配置的一部分。 Xcode库提供对Xcode项目的图像和声音资源的访问,以便您可以将您的nib文件链接到这些资源。 nib文件不直接存储这些资源。相反,它会存储资源文件的名称,以便后面的nib加载代码可以找到它。
当您加载包含对图像或声音资源的引用的nib文件时,nib加载代码会将实际图像或声音文件读取到内存中并进行缓存。在OS X中,图像和声音资源存储在指定的缓存中,以便以后可以在需要时访问它们。在iOS中,只有图像资源存储在指定的缓存中。要访问图像,请使用NSImage
或UIImage
的imageNamed:
方法,具体取决于您的平台。要访问OS X中的缓存声音,请使用NSSound
的soundNamed:
方法。
Nib File Design Guidelines - Nib文件设计指南
在创建你的nib文件时,仔细考虑你打算如何使用该文件中的对象是很重要的。一个非常简单的应用程序可以将其所有用户界面组件存储在单个nib文件中,但对于大多数应用程序,最好将组件分布到多个nib文件中。创建较小的nib文件可让您仅加载需要立即使用的界面部分。它们还可以更轻松地调试您可能遇到的任何问题,因为找到问题的位置较少。
在创建您的nib文件时,请记住以下准则:
考虑延迟加载来设计你的nib文件。规划加载只包含您需要的对象的nib文件。
在OS X应用程序的主要nib文件中,请考虑仅将应用程序菜单栏和可选的应用程序委托对象存储在nib文件中。避免包含在应用程序启动之后才会使用的任何窗口或用户界面元素。相反,将这些资源放在单独的nib文件中,并在启动后根据需要加载它们。
将重复的用户界面组件(如文档窗口)存储在单独的nib文件中。
对于偶尔使用的窗口或菜单,请将其存储在单独的nib文件中。通过将其存储在单独的nib文件中,只有在实际使用它时才会将资源加载到内存中。
使文件所有者成为nib文件之外的任何单点联系对象;请参阅 Accessing the Cntents of a Nib File。
The Nib Object Life Cycle - Nib对象声明周期
当一个nib文件被加载到内存中时,nib加载代码需要几个步骤来确保nib文件中的对象被正确创建和初始化。 了解这些步骤可以帮助您编写更好的控制器代码来管理您的用户界面。
1. The Object Loading Process - 对象加载过程
当您使用NSNib
或NSBundle
的方法加载和实例化nib文件中的对象时,基础的nib加载代码将执行以下操作:
-
- 它将nib文件的内容和任何引用的资源文件加载到内存中:
- 整个nib对象图的原始数据将被加载到内存中,但不会被解档。
- 任何与nib文件关联的自定义图像资源都会被加载并添加到Cocoa图像缓存中;请参阅 About Image and Sound Resources。
- 任何与nib文件关联的自定义声音资源都会被加载并添加到Cocoa声音缓存中;请参阅关 About Image and Sound Resources。
-
- 它解档nib对象图形数据并实例化对象。它如何初始化每个新对象取决于对象的类型以及它在归档中的编码方式。 nib加载代码使用以下规则(按顺序)确定要使用哪种初始化方法。
默认情况下,对象会收到一个
initWithCoder:
消息。在OS X中,标准对象列表包含由系统提供并在缺省Xcode库中可用的视图,单元格,菜单和视图控制器。它还包括使用自定义插件添加到库中的任何第三方对象。即使您更改此类对象的类,Xcode也会将标准对象编码到nib文件中,然后在对象解档时告诉归档程序在您的自定义类中进行交换。在iOS中,任何符合NSCoding
协议的对象都使用initWithCoder:
方法进行初始化。这包括UIView
和UIViewController
的所有子类,无论它们是默认Xcode库还是您定义的自定义类的一部分。OS X中的自定义视图会收到
initWithFrame:
消息。自定义视图是NSView的子类,Xcode没有可用的实现。通常,这些是您在应用程序中定义并用于提供自定义视觉内容的视图。自定义视图不包含标准系统视图(如NSSlider
),这些视图是默认库的一部分或集成第三方插件的一部分。当它遇到自定义视图时,Xcode会将一个特殊的NSCustomView
对象编码到您的nib文件中。自定义视图对象包含构建您指定的实际视图子类所需的信息。在加载时,NSCustomView
对象向实际视图类发送一个alloc
和initWithFrame:
消息,然后为其自身交换结果视图对象。最终结果是真实视图对象处理在nib加载过程中的后续交互。iOS中的自定义视图不使用initWithFrame:
方法进行初始化。除上述步骤中描述的自定义对象外,还会收到
init
消息。
-
- 它重新建立nib文件中对象之间的所有连接
(actions, outlets, and bindings)
。 这包括连接到File’s Owner
和其他占位符对象。 建立连接的方法因平台而异:
-
Outlet connections
在OS X中,nib加载代码首先尝试使用对象自己的方法重新连接outlet。对于每个outlet,Cocoa会查找一个形式为
setOutletName:
的方法并在存在这种方法时调用它。如果找不到这样的方法,Cocoa会在对象中搜索带有相应outlet名称的实例变量,并尝试直接设置该值。如果找不到实例变量,则不会创建连接。设置outlet还会为任何注册的观察者生成键值观察(KVO)通知。这些通知可能在所有对象间连接重新建立之前发生,并且在对象的任何awakeFromNib
方法被调用之前肯定发生。在iOS中,nib加载代码使用
setValue:forKey:
方法重新连接每个outlet。该方法类似地寻找适当的访问器方法,并在失败时回退到其他方式。有关此方法如何设置值的更多信息,请参阅NSKeyValueCoding Protocol Reference。在iOS中设置outlet也会为任何注册的观察者生成KVO通知。这些通知可能在所有对象间连接重新建立之前发生,并且在对象的任何awakeFromNib
方法被调用之前肯定发生。
-
Action connections
- 在OS X中,nib加载代码使用源对象的
setTarget:
和setAction:
方法建立到目标对象的连接。 如果目标对象不响应操作方法,则不会创建连接。 如果目标对象为nil,则该动作由响应者链处理。 - 在iOS中,nib加载代码使用UIControl对象的addTarget:action:forControlEvents:方法来配置操作。 如果目标为nil,则该动作由响应者链处理。
- 在OS X中,nib加载代码使用源对象的
-
Binding
- 在OS X中,Cocoa使用源对象的bind:toObject:withKeyPath:options:方法创建它与其目标对象之间的连接。
- iOS中不支持Bindings。
- 它重新建立nib文件中对象之间的所有连接
-
- 它将一个
awakeFromNib
消息发送到nib文件中定义匹配选择器的相应对象:
- 在OS X中,此消息被发送到定义方法的任何接口对象。 它也被发送到
File's Owner
和定义它的任何占位符对象。 - 在iOS中,此消息仅发送给由nib加载代码实例化的接口对象。 它不会发送到
File's Owner
,First Responder
或任何其他占位符对象。
- 它将一个
- 它显示在nib文件中启用了
Visible at launch time
属性的任何窗口。
- 它显示在nib文件中启用了
无法保证nib加载代码调用对象的awakeFromNib
方法的顺序。 在OS X中,Cocoa试图最后调用文件所有者的awakeFromNib
方法,但不保证这种行为。 如果您需要在加载时进一步配置nib文件中的对象,则最适合的时间是在nib加载调用返回后。 那时,所有的对象都被创建,初始化并准备好使用。
后记
本篇主要讲述了UINib之Nib文件,感兴趣的给个赞或者关注~~~