- Declare explicitly any weak and unretained references.
ARC assumes all object references to be strong. There are exceptions, of course, the best example being the window view (Figure 12). The view keeps strong references to each subview and widget it contains. On the other hand, each subview and widget only keeps a weak reference to its parent view.
Figure 12.
However, it is possible for two ObjC objects to refer to each other strongly. When this happens, you get a circular reference. Consider the sample class in Listing Four.
Listing Four
@interface FooLink { FooLink *fooNext; FooLink *fooPrev; NSData *fooData; NSInteger fooID; } @property(readwrite, assign) FooLink *nextLink; @property(readonly) FooLink *prevLink; - (NSData *)getData; - (void)addToLink:(NSData *)aDat; - (FooLink *)searchForLink:(NSInteger)anID; - (BOOL)hasLink:(NSInteger )anID; //... @end
ClassFooLinkcreates a double-linked list, with each link holding anNSDatainstance. PropertiesfooNextandfooPrevhold pointers to other instances ofFooLink. Since both pointers form a strong reference, ARC will not dispose of the instance.
To prevent this, declare one of the properties as weak. In Listing Five, I placed the directive __weak before the property fooPrev (line 4). Thus, when fooNext points to a nil and the FooLink instance is out of scope, ARC can safely send a release message to the instance.
Listing Five
@interface FooLink { FooLink *fooNext; __weak FooLink *fooPrev; NSData *fooData; NSInteger fooID; } @property(readwrite, assign) FooLink *nextLink; @property(readonly) FooLink *prevLink; - (NSData *)getData; - (void)addToLink:(NSData *)aDat; - (FooLink *)searchForLink:(NSInteger)anID; - (BOOL)hasLink:(NSInteger )anID; //... @end
The__weakdirective declares a reference that can be both weak and a nil. The alternative directive__unsafe_unretaineddeclares one that is weak, but not a nil. Use this directive if you plan to zero out the references yourself. But be sure to do, or you will end up with a memory leak.
There are other compiler directives, of course, but the aforementioned two are the ones you will use often. - Avoid recasting ObjC objects into C-pointers.
Pointers to an ObjC object are of the generic typeid. To use them as input to a C-routine, you could recast the pointer as shown by Listing Six (lines 3-9). Here, I used the factory methodstringWithString:to create anNSStringinstance. Then I recast it into an integer pointer, and pass that pointer to the routinedoFoo.
Listing Six
// Recasting an ObjC object pointer { id tStr; int *tPtr; tStr = [NSString stringWithString:@"foobar"]; tPtr = (int *)tStr; doFoo(tPtr); } // Using a CFObject { CFStringRef tStr; tStr = CFSTR("foobar"); doFoo(tStr); }
However, recasting prevents ARC from managing the object correctly. ARC will not know when to retain the object and when to dispose of it. Moreover, the recast pointer could end up pointing to an invalid object. So, instead of recasting, use Core Foundation APIs to create a C-compatible object (lines 14-17).
- Avoid using ObjC objects as fields in a C
struct.
We can use ObjC objects as fields inside a Cstruct. The samplestructin Listing Seven has two such fields (lines 4-5): one an instance ofNSString, the other ofNSURL. If the ObjC object is a custom one, we could render its properties visible with the@defsdirective.
Listing Seven
// A C struct with ObjC fields typedef struct FooStruct { NSString *fooName; NSURL *fooPath; int fooCount; char *fooData; } Foo; // A C struct with CoreFoundation fields typedef struct BarStruct { CFStringRef *barName; CFURLRef *barPath; int barCount; char *barData; } Bar; // The C struct rewritten as an ObjC class. @interface BarClass { NSString *fooName; NSURL *fooPath; int fooCount; char *fooData; } //...property accessors goes here @end
But here too, ARC will be unable to manage an ObjC object inside astruct. It could not identify references made to that object and provide the rightretain,release, andautoreleasestatements for that object. Again, use Core Foundation APIs to create objects for astruct(lines 13-16). Or rewrite thestructas a simple ObjC class (lines 20-28). - Manage all C and CF objects yourself.
Like garbage collection, ARC ignores all objects created usingstdliband Core Foundation APIs. It will not insert calls tomalloc()andfree(), which are needed to create and dispose of astructor union. Nor will it insert calls toCFRetain()andCFRelease()to retain or dispose of a CF object.
Make sure to supply these calls yourself. Take care to balance each call tomalloc()with a call tofree()and each call toCFRetain()withCFRelease(). Also make sure to avoid calls tofree()orCFRelease()twice on the same object.
Conclusion
Automatic reference counting is an innovative way of managing ObjC objects on MacOS X 10.7 and iOS 5. It does away with explicit retain, release and autorelease messages, and it cuts down potential memory leaks and null pointers. It offers optimized autorelease pools and it avoids the same runtime overhead as garbage collection. It even behaves the same on both platforms. However, there are aspects of ARC too complex to be covered in this space. To learn more about ARC, consult the references listed below.
References
Apple Developer. "Advanced Memory Management Programming Guide." MacOS X Developer Library. https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.pdf [PDF].
Apple Developer. "NSGarbageCollector Class Reference." Mac OS X Developer Library. https://developer.apple.com/library/mac/documentation/Cocoa/Reference/NSGarbageCollector_class/NSGarbageCollector_class.pdf [PDF].
Apple Developer. "Transitioning to ARC Release Notes." iOS Developer Library. http://developer.apple.com/library/ios/releasenotes/ObjectiveC/RN-TransitioningToARC/RN-TransitioningToARC.pdf [PDF].
Apple Developer. "What's New in Xcode." MacOS X Developer Library. http://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/WhatsNewXcode/WhatsNewXcode.pdf [PDF].
LLVM Project. "Automatic Reference Counting." http://clang.llvm.org/docs/AutomaticReferenceCounting.html
Mike Ash. "Automatic Reference Counting." http://www.mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference-counting.html.
Mugunth Kumar. "WWDC 2011, Session 323: Introducing Automatic Reference Counting." http://blog.mugunthkumar.com/articles/migrating-your-code-to-objective-c-arc.
Paul Long. "Understanding Automatic Reference Counting in Objective C." http://longweekendmobile.com/2011/09/07/objc-automatic-reference-counting-in-xcode-explained.
Related Reading
Generating Code Metrics and Estimating Costs with Xcode
JC is a freelance engineering writer based in British Columbia. He frequently contributes articles to MacTech, REALStudio Developer, and Dr. Dobb's. He can be contacted through gmail at anarakisware-at-gmail-dot-com. [Update: A few small corrections were made to this article on June 6, 2012, in response to reader suggestions. Ed.]


