Objective c 在AppKit中开发时,为什么IB创建的属性是assign而不是retain?

Objective c 在AppKit中开发时,为什么IB创建的属性是assign而不是retain?,objective-c,memory-management,appkit,Objective C,Memory Management,Appkit,我是一名经验丰富的iOS开发人员,我决定尝试一些AppKit开发。我在API方面做了一些调整,但在其他方面,我发现OSX开发是“熟悉的” 我一直在Interface Builder中构建AppKit UI,并注意到当我使用所见即所得编辑器在代码文件中创建属性时,Apple正在创建以下内容: @property (assign) IBOutlet NSTableView *tableView; 我觉得这很奇怪,因为在iOS中默认的做事方式会让我这样做: @property (nonatomic,

我是一名经验丰富的iOS开发人员,我决定尝试一些AppKit开发。我在API方面做了一些调整,但在其他方面,我发现OSX开发是“熟悉的”

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

@property (assign) IBOutlet NSTableView *tableView;
我觉得这很奇怪,因为在iOS中默认的做事方式会让我这样做:

@property (nonatomic, retain) IBOutlet NSTableView *tableView;
我意识到,在Mac开发中,我没有和在移动设备上一样的内存限制,在移动设备上,视图可能会被卸载,并且可能需要对UI元素进行强引用

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

为什么苹果在这里创建的是弱引用,而不是强引用?


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

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

(这在
@property
、合成访问器和ARC存在之前是有意义的。)因此,即使相关属性
不安全(后者是
分配
的同义词),所有者实际上也将拥有顶级对象。如果你走另一条路,让这些属性
strong
(又称
保留
),那么FO对每个对象有两种所有权:隐式所有权和
strong
-属性所有权

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

但是,命名为“不安全”
是有原因的(对于对象属性,该名称优先于
assign
)。返回窗口及其视图示例,假设您拥有一个窗口并了解其中一个视图。视图的superview可能是它的唯一所有者,因此,当您关闭窗口(或用户关闭窗口)时,视图将被释放,并因此解除分配。如果视图的属性是不安全的
/
分配
,您仍然知道这个现在已死亡的对象,尝试向视图发送消息可能会导致崩溃或异常

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

(如果您不是文件的所有者,这些都不适用于您,您可能应该声明您认为合适的属性。
可能是一个不错的选择,这取决于您对所有权层次结构的看法以及所引用的对象类型。)

在iOS上,UIKit的作者提出了现在存在问题的隐式保留。你要写自己的所有权;如果你想拥有一个nib或故事板上的对象,你就写了一个
strong
属性,如果你只想知道它,你就写了一个
weak
safe\u unretained
属性,就像你所期望的那样


TL;DR:

我担心这会是答案,但解释得很好。所以我们仍然需要
[tableView release]
中的
[tableView release]
?如果是这样,那么在使用ARC时,该
release
何时会被调用?@MrMage:您通常不会拥有表视图,因为您通常会将其放在nib的窗口或容器视图中,而不会将其放在nib的顶层。您拥有窗口或顶级视图,只需了解表视图即可。您拥有的任何东西都必须释放。@MrMage:在ARC下,
release
消息不存在:
release
消息是非法的(如
retain
autorelease
)。这主要是因为ARC为您发布了强有力的参考资料;如果你被允许自己做这件事,ARC很难思考你在做什么。(这也是为什么它抱怨
性能选择器:
,为什么
@选择器(发布)
也是非法的。)没有
发布
s的一个后果是,您很少需要编写
解除锁定
——任何完全由
[x发布]
消息组成的实现都会消失,编译器为您完成。@MrMage:至于反隐式保留(ARC不知道,因此无法平衡),我在回答中链接的文档建议使用
CFRelease
。这完全是欺骗(在ARC背后),但这是处理nib加载程序在ARC下的隐式保留的唯一方法。