What do you need to know to read and safely touch manual reference counting code?
Predict first
In an MRC file, which call gives you an object you must release?
// A: [[NSString alloc] initWithFormat:@"%d", 1]
// B: [array firstObject]
// C: [NSString stringWithFormat:@"%d", 1]
- A
- B
- C
Mental model. Reading MRC is auditing a ledger kept by hand. Every “taken out” entry needs a matching “returned”, and the missing entries are the bugs.
In a file compiled with -fno-objc-arc you will see retain, release and autorelease written out, and dealloc ending with [super dealloc] (forbidden under ARC). The rule of ownership: you own an object you got from a method starting with alloc, new, copy or mutableCopy, or that you retained, and you must release it exactly once; everything else is borrowed. Property attributes tell you the story: retain and copy own, assign and unsafe_unretained do not (a classic dangling-pointer source for delegates), and weak is zeroing.
Edit these files carefully. Mixing ARC and non-ARC files in one target is allowed (set the flag per file), and it is where bugs hide: ownership has to be balanced at each file boundary. Core Foundation objects need the bridging casts: __bridge (no ownership change), __bridge_retained (hand ownership to CF) and __bridge_transfer (take ownership from CF). When you can, convert the file to ARC with its tests in place, since ARC applies the same rules mechanically.
alloc returns an object you own. The convenience constructor in C returns an autoreleased one, and B returns a borrowed reference.
Common traps
- Releasing an object you borrowed. An over-release crashes later, far from the real mistake.
- Leaving a delegate property as
assign. When the delegate dies, the pointer dangles. Useweak(under ARC) or nil it indealloc.
They might follow up with
- How do you find leaks in MRC code? Instruments Leaks, plus the static analyser, which understands the ownership naming rules.
- Why is
[super dealloc]missing under ARC? The compiler adds the superclass call itself, and writing it is an error.
Related questions
- 3.1.4 What did manual reference counting look like, and which rules did ARC automate?
- 3.6.3 What is Unmanaged, and what do takeRetainedValue and takeUnretainedValue mean?
← How do Objective-C blocks differ from Swift closures, especially for…