Unit 6

Posted ZeroOnet

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unit 6相关的知识,希望对你有一定的参考价值。

什么是沙盒机制?沙盒包含了哪些文件,分别的应用场景是什么?

SandBox(沙盒)是ios管理App的一种安全机制,它规定了应用程序只能访问系统为它创建的文件夹里的内容。下图是一个App的文件夹分级:

  • Documents:Apple建议将程序中创建的文件或者浏览到的文件数据存储到这个文件夹下,iTunes备份和恢复时会包含这个文件夹;
  • Library:
    -> Caches:程序在使用过程中产生的数据缓存会在这个文件夹下体现出来;
    -> Cookies:服务器存放在客户端的用于记录用户信息的小型文本文件(加密);
    -> Preference:存储程序的设置和一些状态信息,在程序中使用NSUserDefault存储的像用户名及密码等用户数据会以属性列表的形式存储在这个位置。
  • tmp:用于存放临时创建的文件。

当收到内存警告时,App会有怎样的处理流程?

这里有各种iOS设备的内存阈值,当内存量达到这样的一个限制值时,App就会被OS强制退出!而这之前系统就会向App发送Memory Warning消息,最开始将通过AppDelegate的如下方法响应:

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application    

然后将内存警告以通知的形式发送给所有的视图控制器,视图控制器就会调用如下方法:

- (void)didReceiveMemoryWarning 
    [super didReceiveMemoryWarning];

    //....

在这里面你应当做的是清除App业务或者缓存数据,而不是手动将视图控制器所持有的视图置为nil这里是不这样做的原因及更好应对内存警告的一些方法。另外在唐巧的技术博客中还提到过OS对内存的优化技巧:

  • 当一段内存被分配时,它会被标记成 In use, 以防止被重复使用。当内存被释放时,这段内存会被标记成Not in use,这样,在有新的内存申请时,这块内存就可能被分配给其它变量。
  • CALayer 包括具体的bitmap内容的私有成员变量类型为 CABackingStore, 当收到MemroyWarning 时, CABackingStore 类型的内存区会被标记成 volatilevolatile 表示这块内存可能会再次被原变量重用。

nib对象从SB中加载到内存到释放经历了怎样的过程?

nib文件装载代码包括文件中创建的对象的实例化、配置以及重建对象之间的连接,其中两个重要的对象是File's OwnerFirst Responder

- - 概述 - -

前者是一个占位符(placeholder)对象,在nib文件加载的时候不会被创建,而是应该在你的代码中创建并将它传递给加载nib的代码,因为这个对象连接着你的应用代码和nib文件中的对象。更具体地说,它是管理nib文件中包含的对象的控制器对象。在Xcode中,你可以File's Ownernib中对象的连接关系。当你加载nib文件时,装载代码会用你指定的更换对象来重建这些连接关系,这样你就可以引用nib文件中的对象和自动接收接口对象的消息。(即这个占位符实际对象会在装载过程中被赋予有意义的值——nib文件的所属对象,然后在重新建立对象与它之间的连接引用关系。)

后者同样是一个占位符对象,它代表了应用中动态确定的响应链的第一个响应对象。因为应用的响应链不能在设计时决定,First Responder(第一响应者)充当一个替身目标来响应任何需要针对于应用的响应链的行为消息。例如UITextField的一系列方法都需要其成为第一响应者才能响应。当你将nib文件加载到内存时,你不需要做任何管理或者替换第一响应者占位符对象的事情,AppKitUIKit框架会在应用当前的配置的基础上建立并持有第一响应者。

- - Nib对象的生命周期 - -

对象的加载过程

当你用NSNib或者NSBundle来加载和初始化nib文件中的对象时,nib装载代码会有如下几步操作:

  1. 加载nib文件内容和任何引用的源文件到内存中:

    ❖ 将整个nib对象图表的原始数据加载到内存但不解档。

    ❖ 将所有与nib文件相互关联的自定义图片和声音资源加载到内存并将它们分别加到Cocoa image / sound cache缓存。

  2. 解档nib对象图表数据并初始化对象。每个新对象如何初始化取决于对象的类型和它在归档时是如何编码的。nib装载代码使用如下规则来决定对象使用哪种初始化方法:

    ❖ 默认情况下,将要初始化的对象会接收到initWithCoder:消息。

    在MacOS中,标准对象包括viewscellsmenus和由系统提供的并在Xcode默认库中可用的view controllers。它还包括使用自定义插件加入到库中的第三方对象。即使你改变了这样一个对象的所属类,Xcode会将标准对象编码到nib文件中并且告诉archiver在解档时将对象所属类交换成你自定义的类。

    在iOS中,任何实现了NSCoding协议的对象将使用initWithCoder:方法来初始化。它包含了所有UIViewUIViewController的子类,无论它是Xcode默认库提供的还是你自己定义的类。

    ❖ 在MacOS中,自定义的views收到initWithFrame:消息。

    自定义views是在Xcode没有有效实现的NSView的子类。特别地,这些是你在程序中定义用来提供自定义可视内容的views。自定义views不包换由默认库或者第三方插件集成的标准系统views

    当偶然使用到自定义view时,Xcode会编码一个特殊的NSCustomView对象到你的nib文件中。自定义view对象包含了你指定的它需要被创建成的真正的view的子类信息。在加载时,NSCustomView对象会发送一个allocinitWithFrame:消息给它真正所属的view类然后互相交换view对象。这样做的效果的是真正的view对象在nib加载过程中处理随后的交互行为。

    iOS中的自定义view不会使用initWithFrame:来初始化。

  3. 重建nib文件中对象之间的所有连接(行为,输出口,绑定),包括File's Owner和其他占位符对象。连接的建立方法与平台有关:

    ❖ 输出口连接(Outlet connections

    ◆ 在MacOS中,nib装载代码首先试图使用对象自身的方法来重新连接输出口。对于每个输出口,Cocoa会寻找setOutletName:这种形式的方法,如果能够找到,就会调用它。如果不能找到,Cocoa会搜索对象与输出口相匹配的实例变量然后试着直接赋值。要是实例变量也没有找到的话,将不会建立任何连接。

    设置输出口也发生在任何注册了观察者的KVO通知,这些通知可能会发生在所有内部对象连接被重建之前,并一定在任何对象调用awakeFromNib方法之前。

    ◆ 在iOS中,nib装载代码使用setValue:forKey:KVC)方法来重建每个输出口连接。该方法同样寻找一个合适的访问方法并在其他方式失败时返回,此时同样没有任何连接建立成功。

    第二种情况同MacOS。

    ❖ 行为连接

    ◆ 在MacOS中,nib装载代码使用源对象的setTarget:setAction:方法来建立到目标对象的连接。如果目标对象不能响应行为方法,连接将不会建立。如果目标对象为nil,就由响应链来处理行为。

    ◆ 在iOS中,nib装载代码使用addTarget:action:forControlEvents:方法来为UIControl对象配置行为。如果目标为nil,行为也将由响应链来处理。

    ❖ 绑定(Bindings

    MacOS支持的特性,iOS没有(与运行时为对象关联属性概念类似)。Cocoa使用bind:toObject:withKeyPath:options:方法为源对象来创建它和它的目标对象之间的关联。

  4. 发送awakeFromNib消息给nib文件中定义了匹配的selector的合适的对象。

    ◆ 在MacOS中,这个消息会发送给任何定义了此方法的接口对象。定义了该方法的File's Owner和任何占位符对象也会受到此消息。

    ◆ 在iOS中,这个消息只会发送给通过nib装载代码来初始化的接口对象。File's OwnerFirst Responder和任何其他的占位符对象不会接收到此消息。

  5. 展示所有在nib文件中Visible at launch time属性使能的windows

nib装载代码调用对象的awakeFromNib方法的顺序是没有保证的。在MacOS中,Cocoa试图最后调用File's OwnerawakeFromNib方法,但这种行为并不能保证。如果你需要在nib文件中配置对象而不是在加载时,最适当的时机是nib加载完毕返回之后。在那时,所有的对象都已经被创建并初始化和准备使用了。

管理nib文件中对象的生命周期

你每次使用NSBundle或者NSNib类来加载nib文件时,底层代码会创建该文件中的对象的新副本,然后将它们返回给你。(nib装载代码不会尝试从之前加载的结果中循环利用nib文件中的对象)如果有必要,你需要确保你已经获得新的对象图表并在你使用完之后解除这种持有关系。典型的情况是,你需要强引用顶层对象来保证它们不会被销毁。你不需要强引用对象图表中级别较低的对象,因为它们由它们的上一级(parents)管理。并且你应该尽可能降低造成强引用循环的风险。

从实际使用出发,iOS和MacOS的输出口都应该被定义为属性(properties)。除了File's Ownernib文件中顶层对象应该是strong强引用外,输出口通常是weak弱引用的。因为:

  • 对于view controller's view或者a window controller's window来说,你创建的输出口是它们的subviews,输出口只是subviews的引用,而不是拥有所有权。
  • 强引用输出口通常指向框架类。(例如,UIViewController's view或者NSWindowController's window输出口)

参考资料

App developer documents:Nib Files

以上是关于Unit 6的主要内容,如果未能解决你的问题,请参考以下文章

iOS 6.1 中的 *** 从 TextFieldOnEditingDidEnd 内部调用成为第一响应者时

视图控制器何时会成为第一响应者?

ViewController 偶尔会在响应者链中丢失?

文件所有者 + 第一响应者

UITableViewCell 中具有第一响应者状态的 UITextField 是不是会阻止单元格重用?

随着vagrant-berkshelf被弃用,是否有可能从Vagrant驱动构建,而Chef只作为供应者?