Should IBOutlets be strong or weak under ARC?

后端 未结 11 2157
自闭症患者
自闭症患者 2020-11-22 01:52

I am developing exclusively for iOS 5 using ARC. Should IBOutlets to UIViews (and subclasses) be strong or weak?

相关标签:
11条回答
  • 2020-11-22 02:40

    I don't see any problem with that. Pre-ARC, I've always made my IBOutlets assign, as they're already retained by their superviews. If you make them weak, you shouldn't have to nil them out in viewDidUnload, as you point out.

    One caveat: You can support iOS 4.x in an ARC project, but if you do, you can't use weak, so you'd have to make them assign, in which case you'd still want to nil the reference in viewDidUnload to avoid a dangling pointer. Here's an example of a dangling pointer bug I've experienced:

    A UIViewController has a UITextField for zip code. It uses CLLocationManager to reverse geocode the user's location and set the zip code. Here's the delegate callback:

    -(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];
    }
    

    I found that if I dismissed this view at the right time and didn't nil self.zip in viewDidUnload, the delegate callback could throw a bad access exception on self.zip.text.

    0 讨论(0)
  • 2020-11-22 02:42

    WARNING, OUTDATED ANSWER: this answer is not up to date as per WWDC 2015, for the correct answer refer to the accepted answer (Daniel Hall) above. This answer will stay for record.


    Summarized from the developer library:

    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;
      
    0 讨论(0)
  • 2020-11-22 02:49

    In iOS development NIB loading is a little bit different from Mac development.

    In Mac development an IBOutlet is usually a weak reference: if you have a subclass of NSViewController only the top-level view will be retained and when you dealloc the controller all its subviews and outlets are freed automatically.

    UiViewController use Key Value Coding to set the outlets using strong references. So when you dealloc your UIViewController, the top view will automatically deallocated, but you must also deallocate all its outlets in the dealloc method.

    In this post from the Big Nerd Ranch, they cover this topic and also explain why using a strong reference in IBOutlet is not a good choice (even if it is recommended by Apple in this case).

    0 讨论(0)
  • 2020-11-22 02:49

    From WWDC 2015 there is a session on Implementing UI Designs in Interface Builder. Around the 32min mark he says that you always want to make your @IBOutlet strong.

    0 讨论(0)
  • 2020-11-22 02:51

    IBOutlet should be strong, for performance reason. See Storyboard Reference, Strong IBOutlet, Scene Dock in iOS 9

    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.

    As of Xcode 7, it suggests strong

    If you watch WWDC 2015 session 407 Implementing UI Designs in Interface Builder, it suggests (transcript from 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.

    0 讨论(0)
提交回复
热议问题