Ios IB插座在电弧下是强还是弱?
我使用ARC专门为iOS 5开发。Ios IB插座在电弧下是强还是弱?,ios,objective-c,cocoa-touch,interface-builder,automatic-ref-counting,Ios,Objective C,Cocoa Touch,Interface Builder,Automatic Ref Counting,我使用ARC专门为iOS 5开发。IBOutlets到UIViews(和子类)应该是strong还是weak 以下是: @property (nonatomic, weak) IBOutlet UIButton *button; 将摆脱所有这些: - (void)viewDidUnload { // ... self.button = nil; // ... } 这样做有什么问题吗?模板正在使用strong以及从“Interface Builder”编辑器直接连接到标
IBOutlet
s到UIView
s(和子类)应该是strong
还是weak
以下是:
@property (nonatomic, weak) IBOutlet UIButton *button;
将摆脱所有这些:
- (void)viewDidUnload
{
// ...
self.button = nil;
// ...
}
这样做有什么问题吗?模板正在使用
strong
以及从“Interface Builder”编辑器直接连接到标题时创建的自动生成属性,但为什么?UIViewController
已经有了一个strong
对其视图的引用,该视图保留了它的子视图。我看不出有任何问题。弧前,我总是让我的IBOutlets分配
,因为它们已经被SuperView保留了下来。如您所指出的,如果您使它们弱
,则不必在viewDidUnload中将它们置零
一个警告:您可以在ARC项目中支持iOS 4.x,但如果支持,则不能使用弱
,因此您必须让它们分配
,在这种情况下,您仍然希望在视图中取消引用以避免指针悬空。下面是我遇到的一个悬空指针错误示例:
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上引发错误的访问异常。在iOS开发中,NIB加载与Mac开发有点不同
在Mac开发中,IBOutlet通常是一个弱引用:如果您有NSViewController的子类,则仅保留顶级视图,当您解除锁定控制器时,其所有子视图和出口都将自动释放
UiViewController使用键值编码来设置使用强引用的出口。因此,当您解除锁定UIViewController时,俯视图将自动解除锁定,但您还必须在解除锁定方法中解除锁定其所有插座
,它们涵盖了这个主题,并解释了为什么在IBOutlet中使用强引用不是一个好的选择(即使在这种情况下是苹果推荐的) 警告,过时答案:根据WWDC 2015,此答案不是最新的,正确答案请参考上面的(Daniel Hall)。这个答案将留作记录
总结如下:
从实际角度来看,在iOS和OS X中,插座应定义为声明的属性。输出通常应该是弱的,除了从文件所有者到nib文件(或者,在iOS中,是情节提要场景)中的顶级对象的输出应该是强的。因此,默认情况下,您创建的插座通常较弱,因为:
- 例如,为视图控制器的视图或窗口控制器的窗口的子视图创建的出口是对象之间的任意引用,并不意味着所有权
- 强输出通常由框架类指定(例如,UIViewController的视图输出或NSWindowController的窗口输出)
我认为最重要的信息是:
xib中的图元自动位于视图的子视图中。子视图是NSArray。NSArray拥有它的元素。etc对它们有很强的指示。因此,在大多数情况下,您不想创建另一个强指针(IBOutlet)
使用ARC,您无需在viewDidUnload
中执行任何操作,而文档建议对子视图的属性使用weak
,因为iOS 6似乎可以使用strong
(默认所有权限定符)相反。这是由于UIViewController
中的更改导致视图不再卸载
- 在iOS 6之前,如果保持与周围控制器视图的子视图的强链接,如果卸载了视图控制器的主视图,则只要视图控制器还在,这些子视图就会一直保留
- 从iOS 6开始,视图不再被卸载,而是加载一次,然后只要控制器还在,视图就会一直保留。所以,强大的属性并不重要。它们也不会创建强引用循环,因为它们指向强引用图
也就是说,我在使用
@property (nonatomic, weak) IBOutlet UIButton *button;
及
在iOS 6及之后:
- 使用
弱
可以清楚地表明控制器不希望拥有按钮
- 但是在没有视图卸载的iOS 6中,省略
弱
不会有什么坏处,而且更短。有些人可能会指出,这也更快,但我还没有遇到过一款应用程序速度太慢,因为太弱
IBOutlet
s
- 不使用
弱
可能被视为错误
一句话:自从iOS 6以来,只要不使用视图卸载,我们就不会再犯这个错误。聚会时间到了 请注意,IBOutletCollection
应该是@property(强,非原子)
来自WWDC 2015,在上有一个会话。在32分钟左右,他说你总是想让你的@IBOutlet
strong苹果公司目前推荐的最佳实践是让IBOutlet变得强大,除非为了避免一个保留周期而特别需要弱。正如Johannes所提到的,在2015年WWDC的“在界面生成器中实现UI设计”会议上,一位苹果工程师表示:
我想指出的最后一个选项是存储类型,它可以
不是强壮就是虚弱。一般来说,你应该让你的出口
strong,尤其是在将插座连接到子视图或
视图不会始终保留的约束
等级制度唯一一次你真的需要让出口变弱
@property (nonatomic, weak) IBOutlet UIButton *button;
@property (nonatomic) IBOutlet UIButton *button;