IBOutlet是否意味着__weak?

6
刚开始使用ARC。在ARC之前,我通常只是声明我的输出口,例如:IBOutlet UIButton *button;,所以我不会保留它或任何东西。在ARC下,不指定弱引用或强引用就意味着强引用。
因此,在ARC下进行相同的操作(即IBOutlet UIButton *button;),这是否意味着button是一个强引用?还是我必须明确将其定义为弱引用?
简而言之,IBOutlet是否意味着__weak?
3个回答

16
这句话的意思是:`IBOutlet`一词实际上没有定义任何东西。
#define IBOutlet

Xcode只是在您的代码中使用此单词的存在,以便允许您在界面构建器中进行连接。将变量或属性声明为IBOutlet:
IBOutlet UIButton * button;
@property (...) IBOutlet UIButton * button;

因此,就ARC而言,它没有任何直接影响;它不会(虽然可能会)转换为__weak或类似的东西。在编译器获得源代码之前,这个单词本身已经完全消失了。
另一方面,这个变量或属性是一个outlet,确实对你需要考虑的内存管理方式有意义。
在ARC下,对象变量声明的隐式存储限定符,如IBOutlet UIButton * button;,是__strong,正如你所说 - 分配给该变量的任何对象都将被视为“拥有”。在MRR下,声明只是一个指针;分配对分配的对象的引用计数/所有权没有影响 - 它的作用方式与assign属性相同。因此,在两种管理系统之间,相同的ivar声明的含义发生了变化。

xib文件中的对象拥有/拥有者关系是由视图层次结构形成的;也就是说,父视图拥有其子视图。xib中的顶层视图由名为File's Owner的对象拥有。这种设置意味着,一般来说,在xib中与顶级对象无关的对象的插座应该是弱引用(在ARC下)或赋值(如果是MRR下的属性)。它们不是拥有关系;它们本质上是方便查看列表的索引。这是苹果公司的建议

“……你不需要强引用图中较低层次的对象,因为它们是由其父级拥有的,你应该尽量减少创建强引用循环的风险。[...]Outlet 应该通常是弱引用,除了从文件所有者到 Nib 文件中的顶层对象(或在 iOS 中,是 Storyboard 场景)的 Outlet 应该是强引用。因此,你创建的 Outlet 通常默认情况下应该是弱引用......”
“像我解释过的那样,您简单的指针 IBOutlet 在内存管理方面起到了类似于弱引用属性的作用,这意味着它们正在做正确的事情。当在 ARC 下编译时,相同的声明将成为可能是错误的。”
总之:IBOutlet 不会被翻译成 weak,但它确实改变了指针的含义。由于在 MRR 下,IBOutlet UIButton * button; 的默认内存管理语义从“assign”变为了 ARC 下的“owned”,而且 IBOutlet 通常应该是非拥有的,因此,IBOutlet 的存在确实意味着指针在 ARC 下应该声明为 __weak

*和weak属性类似——唯一的区别在于,当对象被释放时,weak指针会被设置为nil

**除了自动nil部分。

或者说,它应该是一个weak属性。


谢谢,现在更清楚了。但有一件事我很困惑:即使我不明确将IBOutlet定义为__weak(在这种情况下它会是strong),ARC难道不会处理吗?只要没有保留环(并且没有),一切都被处理好了,对吧? - 0xSina
ARC会继续做它所能做的事情,所以只要你避免保留循环,一个strong IBOutlet也会起作用。 - jscs

4
不,当代码被编译时,IBOutlet基本上会被剥离。然而,它是XCode的一个助手,以便它可以知道什么是InterfaceBuilderOutlet。
基本上,这个词将让您连接界面构建器中的元素。
默认情况下,它仍然是强引用(只需想象该词不存在)。
然而,建议将其设置为弱引用,因为一旦某些东西连接到界面构建器,该接口将保持对它的强引用,因此如果该元素在接口被卸载后不需要保持活动状态,则没有双重强引用的必要。
阅读这个问题,这正是您所寻找的: IBOutlets应该在ARC下是强引用还是弱引用?

1
我必须将我的IBOutlet声明为属性吗? - 0xSina
不需要,你可以将它们声明为实例变量,但如果在MacOS上这样做会有所不同,你可以在这里阅读更多信息:https://dev59.com/7nM_5IYBdhLWcg3wzmgw - Pochi
1
好的,如果我将它们声明为实例变量,最好是这样的:__weak IBOutlet UIButton *button,对吗? - 0xSina
我觉得你正在经历很多麻烦, "__weak IBOutlet UIButton *button;" 是正确的。如果你正在使用ARC和Xcode 4.2,你应该只需打开故事板并选择要引用的元素。然后在编辑器的右上部分单击中间按钮(助理编辑器)。然后只需控制拖动按钮到相应视图控制器的头文件中,无论你将其添加为强引用还是弱引用, Xcode都会处理剩下的部分。(确保助理编辑器设置为自动并选择了正确的头文件) - Pochi

3

IBOutlet关键字仅用于将对象与Interface Builder中的元素关联起来,与弱引用、强引用、ARC或内存管理无关。


2
@JacquesCousteau 不是这样的,请仔细阅读他的回答,IBOutlet关键字与属性设置为强引用或弱引用无关。他说的是100%准确的。无论您决定如何管理对象的内存。 - Pochi
一个带有IBOutlet的属性需要像管理其他属性一样进行管理,但是IBOutlet并不影响它。 - bbarnhart
3
@JacquesCousteau,尽管如此,关键字本身并不暗示或影响任何特定的内存管理策略,这正是这个问题和答案的核心。对于这个问题,这个答案是正确的。 - Firoze Lafeer
1
@0xSina 因为当你将一个属性设置为 strong 时,它的引用计数会增加1,如果你不这样做,当视图消失时指针将会丢失,但对象将保留 +1 的计数,因此会导致内存泄漏。 - Pochi
1
@0xSina 我担心如果我在评论区继续试图向你解释,你会变得更加困惑。请阅读本文的第1部分和第2部分:http://www.raywenderlich.com/5677/beginning-arc-in-ios-5-part-1,它应该能够让你非常清楚地理解。 - Pochi
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接