在AppKit中开发时,为什么IB会创建一个赋值的属性,而不是保留?

Way*_*man 16 memory-management objective-c appkit

我是一名经验丰富的iOS开发者,我决定尝试一些AppKit开发.我正在进行一些API调整,但是否则我发现OS X开发是"熟悉的".

我一直在Interface Builder中构建我的AppKit UI,并注意到当我使用WYSIWYG编辑器在我的代码文件中创建属性时,Apple正在创建以下内容:

@property (assign) IBOutlet NSTableView *tableView;
Run Code Online (Sandbox Code Playgroud)

我发现这很奇怪,因为iOS中默认的做事方式会让我这样做:

@property (nonatomic, retain) IBOutlet NSTableView *tableView;
Run Code Online (Sandbox Code Playgroud)

我意识到在Mac开发中我没有与移动设备相同的内存限制,视图可以卸载,并且可能需要对UI元素进行强引用.

在AppKit的情况下,我可以很好地假设我的UI元素将始终存在,除非我摆弄视图层次结构并将其从父视图中删除.在任何时候都有一个强有力的参考,以防止无意中访问悬空指针似乎是明智的.

为什么Apple会在这里创建一个弱引用,而不是强大的引用呢?

我是否通过使用强引用(但正确释放dealloc)为自己设置了一些意想不到的后果?这里有一些我错过的模式吗?

Pet*_*sey 16

作为文件的所有者,您应该拥有笔尖中的任何和所有顶级对象.您通常不需要拥有这些对象中的任何对象,因为父对象将拥有其子对象; 例如,窗口将拥有其视图.

AppKit的nib加载程序代表文件所有者隐式保留所有顶级对象.(之前有意义@property,合成访问器和ARC存在.)因此,即使相关属性是weakunsafe_unretained(后者是其同义词assign),所有者实际上将拥有顶级对象.如果你走另一条路并制作那些属性strong(又名retain),那么FO 对每个对象有两个所有权:隐式所有权和strong属性所有权.

假设您正在使用手动引用计数,您可以释放隐含的所有权awakeFromNib,但这只是有效.只要你在加载nib后不打算替换任何这些对象(例如,换掉另一个表视图的表视图),一个unsafe_unretained属性就可以正常运行而不需要多余的保留或任何工作.

unsafe_unretainedassign由于某种原因,它被命名为(并且该名称优先于对象属性).返回window-and-its-views示例,假设您拥有一个窗口并了解其中一个视图.视图的超级视图可能是它唯一的所有者,因此,当您关闭窗口(或用户关闭它)时,视图将被释放并因此被释放.如果视图的属性是unsafe_unretained/ assign,您仍然知道这个现在已死的对象,并且尝试向视图发送消息可能会导致崩溃或异常.

您应切换到ARC并将该属性声明为weak.这样,就不会创建冗余所有权,并且该属性将nil在视图终止时自动设置为,从而防止过度释放崩溃.

(如果你不是文件的所有者,没有适用于你,你认为合适你应该声明你的属性.无论是weakstrong可能是一个不错的选择,这取决于你怎么看你的所有权的层次结构,什么样的对象,你'参考.)

在iOS上,UIKit的作者拿出了现在有问题的隐式保留.你应该写自己的所有权; 如果你的意思是从一个笔尖或故事板中拥有一个对象,你就可以写一个strong属性,如果你只是想知道它,你可以写一个weak或者unsafe_unretained一个,就像你期望的那样.

TL; DR: 歇斯底里的原因.