我使用ARC专门为iOS 5开发游戏。iboutlet到UIViews(和子类)是强还是弱?
以下几点:
@property (nonatomic, weak) IBOutlet UIButton *button;
就能摆脱这一切
- (void)viewDidUnload
{
// ...
self.button = nil;
// ...
}
做这个有什么问题吗?模板使用强,当从“接口生成器”编辑器直接连接到头部时,自动生成的属性创建,但为什么?UIViewController已经有一个强引用到它的视图,它保留了它的子视图。
我看不出有什么问题。在arc之前,我总是让IBOutlets赋值,因为它们已经被它们的父视图保留了。如果你把它们设为弱的,你不应该在viewDidUnload中清空它们,正如你指出的那样。
警告:你可以支持iOS 4。x在ARC项目中,但如果你这样做,你不能使用weak,所以你必须让它们赋值,在这种情况下,你仍然想在viewDidUnload中nil引用以避免悬浮指针。下面是我经历过的一个悬浮指针错误的例子:
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];
}
我发现,如果我在正确的时间解散这个视图,没有nil self.zip在viewDidUnload,委托回调可以抛出一个糟糕的访问异常self.zip.text。
目前苹果推荐的最佳实践是iboutlet是强的,除非特别需要弱的以避免保留循环。就像Johannes上面提到的,在2015年WWDC的“在界面生成器中实现UI设计”会议上,一位苹果工程师说:
我想指出的最后一个选项是存储类型,它可以
要么坚强,要么软弱。一般来说,你应该做出口
强,特别是当你连接一个输出到子视图或
约束并不总是会被视图保留
层次结构。唯一真正需要使outlet弱的时候是if
您有一个自定义视图,它引用视图中的备份内容
等级制度,一般来说不建议这样做。
我在Twitter上向IB团队的一位工程师询问了这个问题,他确认strong应该是默认的,并且开发人员文档正在更新。
https://twitter.com/_danielhall/status/620716996326350848
https://twitter.com/_danielhall/status/620717252216623104