我使用ARC专门为iOS 5开发。 IBOutlet
到UIView
s(和子类)的strong
应该是weak
还是@property (nonatomic, weak) IBOutlet UIButton *button;
?
以下内容:
- (void)viewDidUnload
{
// ...
self.button = nil;
// ...
}
将摆脱所有这些:
strong
这样做有什么问题吗?模板使用UIViewController
,因为直接从“Interface Builder”编辑器连接到标题时创建的自动生成属性,但为什么? strong
已对view
的{{1}}引用保留其子视图。
答案 0 :(得分:448)
警告,答案:根据WWDC 2015,此答案不是最新的,正确答案请参阅上面的accepted answer(Daniel Hall)。这个答案将留作记录。
从实际角度来看,在iOS和OS X中,出口应该被定义为声明的属性。 Outlets通常应该是弱的,除了那些从File的Owner到nib文件中的顶级对象(或者,在iOS中,故事板场景)应该很强。因此,默认情况下,您创建的出口通常较弱,因为:
您创建的出口,例如视图控制器视图或窗口控制器窗口的子视图,是不暗示所有权的对象之间的任意引用。
强大的出口通常由框架类指定(例如,UIViewController的视图出口或NSWindowController的窗口出口)。
@property (weak) IBOutlet MyView *viewContainerSubview; @property (strong) IBOutlet MyOtherClass *topLevelObject;
答案 1 :(得分:224)
Apple目前推荐的最佳做法是让IBOutlets 强,除非特别需要 weak 以避免保留周期。正如Johannes上面提到的,在WWDC 2015的“实现界面生成器中的UI设计”会话中对此进行了评论,Apple工程师说:
我想指出的最后一个选项是存储类型,可以 无论是强者还是弱者。一般来说,你应该做出自己的出路 强大,特别是如果您将插座连接到子视图或 视图并不总是保留的约束 层次结构。你真正需要做出一个弱点的唯一一次是if 你有一个自定义视图,引用备份视图的东西 层次结构,一般不推荐。
我在Twitter上向IB团队的工程师询问了这一点,他确认 strong 应该是默认的,并且开发人员文档正在更新。
https://twitter.com/_danielhall/status/620716996326350848 https://twitter.com/_danielhall/status/620717252216623104
答案 2 :(得分:48)
虽然文档建议在子视图的属性上使用weak
,但是从iOS 6开始,使用strong
(默认的所有权限定符)似乎没问题。这是由于通过UIViewController
中的更改,视图不再被卸载。
那就是说,我在使用
之间挣扎@property (nonatomic, weak) IBOutlet UIButton *button;
和
@property (nonatomic) IBOutlet UIButton *button;
在iOS 6及之后:
使用weak
清楚地说明控制器不想要按钮的所有权。
但是在没有视图卸载的情况下省略weak
在iOS 6中没有受到伤害,而且更短。有些人可能会指出也更快,但由于weak
IBOutlet
s,我还没有遇到过慢的应用。
不使用weak
可能会被视为错误。
结论:从iOS 6开始,只要我们不使用视图卸载,我们就不会再出错了。聚会的时间。 ;)
答案 3 :(得分:34)
我没有看到任何问题。在ARC之前,我总是制作我的IBOutlets assign
,因为他们的超级视图已经保留了它们。如果你制作它们weak
,你应该不必在viewDidUnload中将它们取出,正如你所指出的那样。
一个警告:您可以在ARC项目中支持iOS 4.x,但如果这样做,则无法使用weak
,因此您必须使用assign
,其中你仍然希望在viewDidUnload
中取消引用以避免悬空指针。这是我经历过的悬空指针错误的一个例子:
UIViewController有一个UITextField用于邮政编码。它使用CLLocationManager反转地理编码用户的位置并设置邮政编码。这是委托回调:
-(void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
Class geocoderClass = NSClassFromString(@"CLGeocoder");
if (geocoderClass && IsEmpty(self.zip.text)) {
id geocoder = [[geocoderClass alloc] init];
[geocoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray *placemarks, NSError *error) {
if (self.zip && IsEmpty(self.zip.text)) {
self.zip.text = [[placemarks objectAtIndex:0] postalCode];
}
}];
}
[self.locationManager stopUpdatingLocation];
}
我发现如果我在正确的时间解散了这个视图并且没有在viewDidUnload
中使用self.zip,则委托回调可能会在self.zip.text上抛出一个错误的访问异常。
答案 4 :(得分:20)
在iOS开发中,NIB加载与Mac开发略有不同。
在Mac开发中,IBOutlet通常是一个弱引用:如果你有一个NSViewController的子类,只保留顶级视图,当你释放控制器时,它的所有子视图和出口都会被自动释放。
UiViewController使用键值编码来使用强引用设置出口。因此,当您释放UIViewController时,顶视图将自动解除分配,但您还必须在dealloc方法中释放其所有出口。
In this post from the Big Nerd Ranch,它们涵盖了这个主题,并解释了为什么在IBOutlet中使用强引用不是一个好的选择(即使在这种情况下Apple推荐它)。
答案 5 :(得分:20)
sudo service nginx restart
应该很强大。见Storyboard Reference, Strong IBOutlet, Scene Dock in iOS 9
如本段所述,视图子视图的出口 控制器的视图可能很弱,因为这些子视图已经存在 由nib文件的顶级对象拥有。但是,当一个奥特莱斯 被定义为弱指针并且指针被设置,ARC调用 运行时功能:
IBOutlet
这会添加指针 (对象)使用对象值作为键的表。这张桌子是 被称为弱表。 ARC使用此表存储所有 你的应用程序的弱指针。现在,当对象值是 取消分配后,ARC将遍历弱表并设置弱点 参考零。或者,ARC可以致电:
id objc_storeWeak(id *object, id value);
然后,对象是 unregistered和objc_destroyWeak再次调用:
void objc_destroyWeak(id * object)
这本书保持联系 弱引用可能比释放a长2-3倍 强烈的参考。因此,弱引用引入了开销 通过简单地将出口定义为强大而可以避免的运行时。
从Xcode 7开始,它建议objc_storeWeak(id *object, nil)
如果你观看WWDC 2015会话407 Implementing UI Designs in Interface Builder,它建议(来自http://asciiwwdc.com/2015/sessions/407的成绩单)
我想指出的最后一个选项是存储类型,它可以是强也可以是弱。
一般情况下,您应该使您的插座强大,特别是如果您将插座连接到子视图或视图层次结构并不总是保留的约束。
你唯一真正需要让出口变弱的一个方法就是如果你有一个自定义视图引用视图层次结构中的某些内容,而且通常不推荐这样做。
所以我要选择强力,我会点击连接,这将产生我的插座。
答案 6 :(得分:15)
我想在此指出一点,那就是,尽管Apple工程师在他们自己的WWDC 2015视频中已经说明了这一点:
https://developer.apple.com/videos/play/wwdc2015/407/
Apple不断改变主题,这告诉我们这个问题没有一个正确答案。为了表明即使苹果公司的工程师在这个问题上存在分歧,请看看Apple的最新版本 示例代码,您会看到有些人使用弱,而有些人不会。
所有这些都针对iOS 9进行了全面更新,并且都使用弱插座。由此我们了解到A.问题并不像有些人想象的那么简单。 B. Apple反复改变主意,C。你可以使用任何让你开心的事情:)
特别感谢Paul Hudson(www.hackingwithsift.com的作者)给我的澄清,以及对此答案的参考。
我希望这能更好地澄清这个主题!
小心。
答案 7 :(得分:9)
来自WWDC 2015的Implementing UI Designs in Interface Builder会话。在32分钟左右,他说你总是希望让你的@IBOutlet
强大。
答案 8 :(得分:6)
请注意,IBOutletCollection
应为@property (strong, nonatomic)
。
答案 9 :(得分:5)
多年来似乎发生了一些变化,现在Apple建议使用强大的功能。 WWDC会议的证据在session 407 - Implementing UI Designs in Interface Builder,从32:30开始。我所说的是(几乎,如果不完全是,引用他):
出口连接一般应该很强,特别是如果我们连接的子视图或约束并不总是由 查看层次结构
创建自定义视图时可能需要弱插座连接,该视图对视图层次结构中备份的内容有一些参考 一般情况下不推荐
在其他病房中,只要我们的某些自定义视图没有在视图层次结构中创建一些视图的保留周期,它就应该总是很强大
编辑:
有些人可能会问这个问题。使用强引用保留它不会创建保留周期,因为根视图控制器和拥有视图会保留对它的引用吗?或者为什么发生了变化? 我认为当他们描述如何从xib创建笔尖时,答案在本次演讲中更早。为VC和视图创建了一个单独的nib。我认为这可能是他们改变建议的原因。从Apple那里得到更深入的解释仍然会很好。
答案 10 :(得分:4)
我认为最重要的信息是: xib中的元素自动位于视图的子视图中。子视图是NSArray。 NSArray拥有它的元素。等等有强烈的指针。所以在大多数情况下你不想创建另一个强指针(IBOutlet)
使用ARC,您无需在viewDidUnload