Like many of you, I’ve recently starting coming to terms with automatic reference counting (ARC) in Objective-C. For the most part, it’s gone remarkably smoothly. The only hard part is remembering to not type autorelease!
ARC lets us get rid of the retain/release pairs in our code. But can you spot the bug in the following code?
@interface MyObject : NSObject @property (copy) id ivar; @end @implementation MyObject @synthesize ivar = _ivar; - (id)initWithIvar:(id)ivar { self = [super init]; if (self != nil) { _ivar = ivar; } return self; } @end
The ivar instance variable is a strong reference, not a copy. Since I think it’s a bad idea to use accessors during -init the copy semantics defined by the @property are never used and ARC happily retains the reference instead of copying it. Also of note: the static analyzer doesn’t think there’s anything wrong with the code above, so you won’t see any warnings that you’ve screwed up.
In my case, this initializer led to a bug where several worker threads were modifying the same instance variable and, well, you know how that goes. The fix, as usual, was painfully simple:
_ivar = [ivar copy];
It’s important to remember that ARC primarily affects how we use -retain and -release. As Matt Drance points out the way -copy works hasn’t changed significantly. Just because we can forget about typing “retain” and “release”, doesn’t necessarily mean that we can forget to type “copy”, too.
Updated May 4th, 2012: A Radar about the static analyzer not issuing a warning has been filed: rdar://11386493