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?
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 areweakorunsafe_unretained(the latter being a synonym forassign), the owner will in fact own the top-level objects. And if you go the other way and make those propertiesstrong(a.k.a.retain), then the FO has two ownerships of each object: the implicit ownership, and thestrong-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), anunsafe_unretainedproperty will work just fine without a superfluous retain or any made work.unsafe_unretainedis named that (and that name is preferred overassignfor 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 isunsafe_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 tonilwhen 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
weakorstrongmay 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
strongproperty, and if you mean only to know about it, you write aweakorunsafe_unretainedone, exactly as you’d expect.TL;DR: Hysterical reasons.