Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When developing in AppKit, why does IB create a property that is assign, rather than retain?

I'm an experienced iOS dev and I have decided to try my hand at some AppKit development. There are a couple of adjustments that I am making API-wise, but otherwise am finding OS X development to be, shall we say, 'familiar'.

I've been building my AppKit UIs in Interface Builder and noticed that when I use the WYSIWYG editor to create properties in my code files, Apple is creating the following:

@property (assign) IBOutlet NSTableView *tableView;

I find this very curious because the default way of doing things in iOS would have led me to do this:

@property (nonatomic, retain) IBOutlet NSTableView *tableView;

I realize that in Mac development I don't have the same memory constraints that I do on mobile, where a view could get unloaded and there may be a need for strong references to UI elements.

In the AppKit case I can pretty well assume that my UI elements will always be there unless I fiddle with the view hierarchy and remove it from its parent view. It would seem prudent to have a strong reference at all times in order to guard against unintentionally accessing dangling pointers.

Why is Apple creating a weak reference here, instead of a strong one?

Am I setting myself up for some unintended consequence by using strong references (but properly releasing in dealloc)? Is there some pattern here that I am missing?

like image 399
Wayne Hartman Avatar asked Aug 30 '12 03:08

Wayne Hartman


1 Answers

As File's Owner, you should own any and all top-level objects in the nib. You generally do not need to own any objects within those objects, because a parent object will own its child objects; for example, a window will own its views.

AppKit's nib loader implicitly retains all top-level objects on behalf of the File's Owner. (This made sense before @property, synthesized accessors, and ARC existed.) Thus, even if the relevant properties are weak or unsafe_unretained (the latter being a synonym for assign), the owner will in fact own the top-level objects. And if you go the other way and make those properties strong (a.k.a. retain), then the FO has two ownerships of each object: the implicit ownership, and the strong-property ownership.

Assuming you're using manual reference counting, you can release the implicit ownership in awakeFromNib, but that's just made work. As long as you're not going to replace any of those objects after the nib is loaded (e.g., swap out a table view for another table view), an unsafe_unretained property will work just fine without a superfluous retain or any made work.

unsafe_unretained is named that (and that name is preferred over assign for object properties) for a reason, though. Returning the window-and-its-views example, suppose you own a window and know about one of its views. The view's superview is probably its only owner, so, when you close the window (or the user closes it), the view will get released and consequently deallocated. If your property to the view is unsafe_unretained/assign, you still know about this now-dead object, and trying to send a message to the view may cause a crash or an exception.

You should switch to ARC and declare the property as weak. That way, no redundant ownership is created, and the property will automatically be set to nil when the view dies, preventing an over-release crash from ensuing.

(If you're not the File's Owner, none of that applies to you and you should probably declare your properties as you see fit. Either weak or strong may be a good choice, depending on how you see your ownership hierarchy and what kind of object you're referencing.)

On iOS, UIKit's authors took out the now-problematic implicit retain. You are expected to write your own ownerships; if you mean to own an object from a nib or storyboard, you write a strong property, and if you mean only to know about it, you write a weak or unsafe_unretained one, exactly as you'd expect.

TL;DR: Hysterical reasons.

like image 140
Peter Hosey Avatar answered Oct 16 '22 08:10

Peter Hosey