我使用ARC专门为iOS 5开发游戏。iboutlet到UIViews(和子类)是强还是弱?
以下几点:
@property (nonatomic, weak) IBOutlet UIButton *button;
就能摆脱这一切
- (void)viewDidUnload
{
// ...
self.button = nil;
// ...
}
做这个有什么问题吗?模板使用强,当从“接口生成器”编辑器直接连接到头部时,自动生成的属性创建,但为什么?UIViewController已经有一个强引用到它的视图,它保留了它的子视图。
出于性能考虑,IBOutlet应该是强大的。参见iOS 9中的故事板参考,Strong IBOutlet, Scene Dock
As explained in this paragraph, the outlets to subviews of the view
controller’s view can be weak, because these subviews are already
owned by the top-level object of the nib file. However, when an Outlet
is defined as a weak pointer and the pointer is set, ARC calls the
runtime function:
id objc_storeWeak(id *object, id value);
This adds the pointer
(object) to a table using the object value as a key. This table is
referred to as the weak table. ARC uses this table to store all the
weak pointers of your application. Now, when the object value is
deallocated, ARC will iterate over the weak table and set the weak
reference to nil. Alternatively, ARC can call:
void objc_destroyWeak(id * object)
Then, the object is
unregistered and objc_destroyWeak calls again:
objc_storeWeak(id *object, nil)
This book-keeping associated
with a weak reference can take 2–3 times longer over the release of a
strong reference. So, a weak reference introduces an overhead for the
runtime that you can avoid by simply defining outlets as strong.
在Xcode 7中,它是强的
如果你观看了WWDC 2015会议407在界面生成器中实现UI设计,它建议(来自http://asciiwwdc.com/2015/sessions/407)
And the last option I want to point out is the storage type, which can either be strong or weak.
In general you should make your outlet strong, especially if you are connecting an outlet to a sub view or to a constraint that's not always going to be retained by the view hierarchy.
The only time you really need to make an outlet weak is if you have a custom view that references something back up the view hierarchy and in general that's not recommended.
So I'm going to choose strong and I will click connect which will generate my outlet.
出于性能考虑,IBOutlet应该是强大的。参见iOS 9中的故事板参考,Strong IBOutlet, Scene Dock
As explained in this paragraph, the outlets to subviews of the view
controller’s view can be weak, because these subviews are already
owned by the top-level object of the nib file. However, when an Outlet
is defined as a weak pointer and the pointer is set, ARC calls the
runtime function:
id objc_storeWeak(id *object, id value);
This adds the pointer
(object) to a table using the object value as a key. This table is
referred to as the weak table. ARC uses this table to store all the
weak pointers of your application. Now, when the object value is
deallocated, ARC will iterate over the weak table and set the weak
reference to nil. Alternatively, ARC can call:
void objc_destroyWeak(id * object)
Then, the object is
unregistered and objc_destroyWeak calls again:
objc_storeWeak(id *object, nil)
This book-keeping associated
with a weak reference can take 2–3 times longer over the release of a
strong reference. So, a weak reference introduces an overhead for the
runtime that you can avoid by simply defining outlets as strong.
在Xcode 7中,它是强的
如果你观看了WWDC 2015会议407在界面生成器中实现UI设计,它建议(来自http://asciiwwdc.com/2015/sessions/407)
And the last option I want to point out is the storage type, which can either be strong or weak.
In general you should make your outlet strong, especially if you are connecting an outlet to a sub view or to a constraint that's not always going to be retained by the view hierarchy.
The only time you really need to make an outlet weak is if you have a custom view that references something back up the view hierarchy and in general that's not recommended.
So I'm going to choose strong and I will click connect which will generate my outlet.
警告,过时的答案:根据WWDC 2015,这个答案不是最新的,正确答案参考上面的公认答案(丹尼尔·霍尔)。这个答案将被记录下来。
从开发人员库总结:
From a practical perspective, in iOS and OS X outlets should be defined as declared properties. Outlets should generally be weak, except for those from File’s Owner to top-level objects in a nib file (or, in iOS, a storyboard scene) which should be strong. Outlets that you create will therefore typically be weak by default, because:
Outlets that you create to, for example, subviews of a view controller’s view or a window controller’s window, are arbitrary references between objects that do not imply ownership.
The strong outlets are frequently specified by framework classes (for example, UIViewController’s view outlet, or NSWindowController’s window outlet).
@property (weak) IBOutlet MyView *viewContainerSubview;
@property (strong) IBOutlet MyOtherClass *topLevelObject;
我看不出有什么问题。在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。