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



我是一名经验丰富的iOS开发人员,我决定尝试一下AppKit的开发。我正在做一些API化的调整,但除此之外,我发现OS X的开发是"熟悉的"。

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

@property (assign) IBOutlet NSTableView *tableView;

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

@property (nonatomic, retain) IBOutlet NSTableView *tableView;

我意识到,在Mac开发中,我没有像在移动设备上那样的内存限制,在移动设备中,视图可能会被卸载,并且可能需要对UI元素的强引用。

在AppKit的情况下,我可以很好地假设我的UI元素将始终存在,除非我篡改视图层次结构并将其从其父视图中删除。为了防止无意中访问悬挂指针,在任何时候都要有一个强引用似乎是谨慎的。

为什么苹果在这里创建了一个弱引用,而不是一个强引用

我是否通过使用强引用(但在dealloc中正确发布)为自己设置了一些意外后果?这里有我遗漏的图案吗

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

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

假设您使用手动引用计数,您可以释放awakeFromNib中的隐含所有权,但这只是工作。只要在加载nib后不替换这些对象中的任何一个(例如,将一个表视图换成其他表视图),unsafe_unretained属性就可以正常工作,而不会有多余的保留或任何已完成的工作。

unsafe_unretained的命名是有原因的(对于对象属性,这个名称比assign更可取)。返回窗口及其视图示例,假设您拥有一个窗口并了解其中一个视图。视图的超级视图可能是它的唯一所有者,因此,当您关闭窗口(或用户关闭它)时,视图将被释放,从而被释放。如果视图的属性是unsafe_unretained/assign,那么您仍然知道这个现在已经死了的对象,并且尝试向视图发送消息可能会导致崩溃或异常。

您应该切换到ARC并将属性声明为weak。这样,就不会创建多余的所有权,并且当视图失效时,属性将自动设置为nil,从而防止过度发布崩溃。

(如果你不是文件的所有者,这些都不适用于你,你可能应该根据自己的意愿声明你的属性。weakstrong可能是一个不错的选择,这取决于你如何看待你的所有权层次结构以及你引用的对象类型。)

在iOS上,UIKit的作者去掉了现在有问题的隐式保留。你应该写下你自己的所有权;如果你想拥有笔尖或故事板上的一个对象,你可以写一个strong属性,如果你只想知道它,你可以像你期望的那样写一个weakunsafe_unretained属性。

TL;DR:滞后原因。

最新更新