Channels ▼
RSS

Mobile

Automatic Reference Counting on iOS




  • 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
    

    Class FooLink creates a double-linked list, with each link holding an NSData instance. Properties fooNext and fooPrev hold pointers to other instances of FooLink. 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 __weak directive declares a reference that can be both weak and a nil. The alternative directive __unsafe_unretained declares 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 type id. 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 method stringWithString: to create an NSString instance. Then I recast it into an integer pointer, and pass that pointer to the routine doFoo.

    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 C struct. The sample struct in Listing Seven has two such fields (lines 4-5): one an instance of NSString, the other of NSURL. If the ObjC object is a custom one, we could render its properties visible with the @defs directive.

    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 a struct. It could not identify references made to that object and provide the right retain, release, and autorelease statements for that object. Again, use Core Foundation APIs to create objects for a struct (lines 13-16). Or rewrite the struct as a simple ObjC class (lines 20-28).
  • Manage all C and CF objects yourself.
    Like garbage collection, ARC ignores all objects created using stdlib and Core Foundation APIs. It will not insert calls to malloc() and free(), which are needed to create and dispose of a struct or union. Nor will it insert calls to CFRetain() and CFRelease() to retain or dispose of a CF object.
    Make sure to supply these calls yourself. Take care to balance each call to malloc() with a call to free() and each call to CFRetain() with CFRelease(). Also make sure to avoid calls to free() or CFRelease() 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

Managing Memory on iOS

Generating Code Metrics and Estimating Costs with Xcode

Mastering Threads on MacOS X

Cocoa Memory Management


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.]


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video