修饰 outlet 用 Strong 还是 Weak?

Outlet是一个对象的属性(property),这个属性引用了另外一个对象(在nib文件中),它们的引用关系被Interface Builder记录着,每次nib文件被使用来生成视图时,这些引用关系都会被创建,使得该nib文件中的对象与另一个对象中被标记为outlet的属性产生联系.如:

1
@interface GallantViewController : UIViewController
2
@property (nonatomic, weak) IBOutlet UISwitch *switch;
3
@end

而IBOutlet不是OC中的语法,只是在Xcode中为了让Interface Builder更好的识别出一个属性是outlet而添加的.它的宏定义如下:

1
#define IBOutlet

由Clang可知,实际上它是被编译器定义成:

1
#define IBOutlet __attribute__((iboutlet))

和其他属性一样,被用作outlet的属性也可用weak(在MRC下用assign)或strong来修饰,而strong 是默认的.
在app通常用outlet来连接自定义的控制器对象和用户界面上的对象.

官方文档认为:一个outlet应该使用weak来声明为弱引用,除非是从File’s Owner到nib文件中的顶层(top-level)对象(如storyboard scene).理由有:
(1) 因为这样可以避免循环引用问题;
(2) 那些指向视图控制器的view或窗口控制器的window的子视图,只是对象间比较随意的引用,并没用拥有关系,所以不应用strong
(3) 用strong修饰的outlet通常是在框架类来制定(如视图控制器的视图outlet)

1
@property (weak) IBOutlet MyView *viewContainerSubview;
2
3
@property (strong) IBOutlet MyOtherClass *topLevelObject;

但又指出outlet越多,占用的内存也越多.所以推荐使用其他方法来引用Interface Builder上的对象,如在矩阵中的位置,函数参数,或者用tag.
也有些情况应该用strong修饰outlet:
(1) 从File’s Owner到nib文件中的顶层对象;
(2) 在希望某nib文件中的对象能在脱离它原来的容器还存活的情况.如想要使用一个视图,而这个视图随时可能从其所在的视图层次(view hierarchy)中被删除,则可用strong来修饰与这个视图的outlet,使之能独立存在.

而在WWDC 2015的”Implementing UI Designs in Interface Builder”会议,则有个Apple的工程师说:
“通常你应该用strong来修饰你的outlet,尤其是当你要连接一个outlet到子视图或者在视图层次中不总是被持有的constraint(约束?)时.只有当你用自定义的视图来引用一个东东,而这个东东反过来又引用了视图层次时才需要用weak,但还是不推荐这么做.”

也有人认为从性能方面论证应该尽量用Strong来修饰outlet:访问weak修饰的属性效率更低.因为访问一个strong,nonatomic的属性只是读取和返回一个指针值,而访问一个weak,nonatomic的属性需要几步:确认该对象未被标记为deallocated,对其值使用retain和autorelease(否则返回的指针随时可能无效),要访问的每部分还要被锁上.weak修饰outlet虽然在释放顶层视图时免了显式清除,但卸载(unload)顶层视图本来就很难正确,所以Apple在iOS6之后就不用unload了.

另外,在Swift中,修饰属性的不仅有strong/weak,还有可选类型的”!”或”?”。这时情况可分一下几种:
(1) 如果可以保证一个视图总会存在,则用strong + ”!”,这样访问outlet属性总能有值。这种也是最常用的。

1
@IBOutlet private var someLabel: UILabel!

(2) 如果一个视图有可能不作为视图层次结构中的一部分而存在时,则用strong + ”?”,这样说明访问outlet时不一定能保证有值.

1
@IBOutlet private var someLabel: UILabel?

(3) 如果一个视图从视图层次结构中移除后不再需要被用到,则可以用weak + “?”使得该视图被移除后释放内存。

1
@IBOutlet private weak var someLabel: UILabel?

参考:

Strong Feelings on Weak Outlets

IBAction / IBOutlet / IBOutlet​Collection

Outlets: Strong! Or Weak?

IBOutlets strong or weak

Outlets

ARC下IBOutlet用weak还是strong