Automatic Reference
Counting
Robert Brown
@robby_brown
What is ARC?
Automatic Reference Counting
  Similar to using smart pointers
Never need to call -release or -autorelease
More efficient than garbage collection
No more memory leaks!
  Doesn’t handle retain loops
What is ARC?


Includes a weak reference system (Lion/iOS 5.0+)
ARC code works with non-ARC code and vice versa
Xcode 4.2+ only
Manual Reference Counting
Just to help you appreciate ARC...
  Retain: +1 retain count (claim ownership)
  Release: -1 retain count (revoke ownership)
  Autorelease: Ownership is transferred to latest
  autorelease pool on the current thread
  When retain count reaches 0, the object is deleted.
With ARC you ignore all of this
New Rules


You cannot explicitly invoke dealloc, or implement or
invoke retain, release, retainCount, or autorelease.
  The prohibition extends to using @selector(retain),
  @selector(release), and so on.
New Rules

You may implement a dealloc method if you need to
manage resources other than releasing instance
variables. You do not have to (indeed you cannot)
release instance variables, but you may need to invoke
[systemClassInstance setDelegate:nil] on system
classes and other code that isn’t compiled using ARC.
New Rules

Custom dealloc methods in ARC do not require a call
to [super dealloc] (it actually results in a compiler error).
The chaining to super is automated and enforced by
the compiler.
You can still use CFRetain, CFRelease, and other
related functions with Core Foundation-style objects.
New Rules

You cannot use NSAllocateObject or
NSDeallocateObject.
You create objects using alloc; the runtime takes care
of deallocating objects.
You cannot use object pointers in C structures.
  Rather than using a struct, you can create an
  Objective-C class to manage the data instead.
New Rules

There is no casual casting between id and void *.
You must use special casts that tell the compiler about
object lifetime. You need to do this to cast between
Objective-C objects and Core Foundation types that
you pass as function arguments.
New Rules

Cannot use NSAutoreleasePool objects.
  ARC provides @autoreleasepool blocks instead.
  These have an advantage of being more efficient
  than NSAutoreleasePool.
You cannot use memory zones.
  There is no need to use NSZone any more—they are
  ignored by the modern Objective-C runtime anyway.
New Rules

To allow interoperation with manual retain-release code,
ARC imposes some constraints on method and
variable naming:
  You cannot give a property a name that begins with
  new.
New Rules

Summary:
 ARC does a lot of stuff for you. Just write your code
 and trust ARC to do the right thing.
 If you write C code, then you actually have to do
 some work.
Old way:                        ARC way:

NSAutoreleasePool * pool =      @autoreleasepool {    // This is cool!
[NSAutoreleasePool new];

NSArray * comps = [NSArray      NSArray * comps = [NSArray
arrayWithObjects:@"BYU",        arrayWithObjects:@"BYU",
@"CocoaHeads", nil];            @"CocoaHeads", nil];

NSString * path = [NSString     NSString * path = [NSString
pathWithComponents:comps];      pathWithComponents:comps];

NSURL * url = [[NSURL alloc]    NSURL * url = [[NSURL alloc]
initWithPath:path];             initWithPath:path];

// Do something with the URL.   // Do something with the URL.

[url release];                  // Hey look! No release!

[pool drain];                   }   // Automatic drain!
Automatic Conversion

1.Edit > Refactor > Convert to Objective-C ARC
2.Select the files you want to convert (probably all)
3.Xcode will let you know if it can’t convert certain parts
     You may want to continue on errors
     Xcode > Preferences > General > Continue building
     after errors
Demo
Weak Referencing
Weak reference doesn’t increment retain count
Weak reference is nilled when the object is dealloc’d
Adds some overhead due to bookkeeping
Great for delegates
  @property(nonatomic, weak) id delegate;
iOS 5.0+
IBOutlets
 Weak reference:         Strong reference:
   Used only with non-     Must be used for top-
   top-level IBOutlets     level IBOutlets
   Automatically nils      May be used for non-
   IBOutlet in low         top-level IBOutlets
   memory condition
                           Manually nil IBOutlet in
   Requires some extra     -viewDidUnload
   overhead
Advanced ARC
Lifetime Qualifiers                  Jedi
                                    Level




 __strong
   A retained reference (default)
 __weak
   Uses weak reference system
Lifetime Qualifiers                             Jedi
                                               Level




 __unsafe_unretained
   Unretained reference—like assign property
 __autoreleasing
   Autoreleased reference
What About C?                                  Jedi
                                               Level




ARC does not manage memory for C
You must call free() for every malloc()
  Core Foundation objects use CFRelease()
Toll-free bridging requires an extra keyword
Bridging                   Jedi
                           Level




__bridge
  Straight bridge cast
__bridge_transfer
  -1 to the retain count
__bridge_retained
  +1 to the retain count
Bridging Made Easy                    Jedi
                                      Level




The casts are hard to remember
Use these macros instead:
  CFBridgingRetain(obj) = ARC to C
  CFBridgingRelease(obj) = C to ARC
Disabling ARC                                      Jedi
                                                   Level




ARC can be disabled on a file-level.
Project file > Main target > Build phases > Compile
sources > Add compiler flag “-fno-objc-arc”
If ARC is not on by default, it can be turned on
manually with “-fobjc-arc”
Demo
Blocks                                                   Jedi
                                                         Level




// WARNING: Retain loop!
// The static analyzer will warn you about this.
[self setBlock:^{
    [self doSomething];
    [_ivar doSomethingElse]; // Implicitly self->_ivar
}
Blocks                                            Jedi
                                                  Level




// No retain loop
__block __unsafe_unretained id unretainedSelf = self;
[self setBlock:^{
    [unretainedSelf doSomething];
    [[unretainedSelf var] doSomethingElse];
}
Blocks                                  Jedi
                                        Level




// Better alternative (iOS 5.0+)
__weak id weakSelf = self;
[self setBlock:^{
    [weakSelf doSomething];
    [[weakSelf var] doSomethingElse];
}
Return by Reference                                Jedi
                                                   Level




Return by reference is fairly common, especially with
NSError.
Example:
-(BOOL)save:(NSError *__autoreleasing*)outError;
Return by Reference                              Jedi
                                                 Level




// What you write
NSError * error = nil; // Implicitly __strong.
if (![self save:&error]) {
     // An error occurred.
 }
Return by Reference                      Jedi
                                         Level




// What ARC writes
NSError * __strong error = nil;
NSError * __autoreleasing tmp = error;
if (![self save:&tmp]) {
     // An error occurred.
 }
Return by Reference                                     Jedi
                                                        Level




// This isn’t a big deal, but it avoids the temporary
variable
NSError * __autoreleasing error = nil;
if (![self save:&error]) {
     // An error occurred.
 }
Questions?
Want to Learn More?


WWDC 2011: Session 323
Transitioning to ARC Release Notes

Automatic Reference Counting

  • 1.
  • 2.
    What is ARC? AutomaticReference Counting Similar to using smart pointers Never need to call -release or -autorelease More efficient than garbage collection No more memory leaks! Doesn’t handle retain loops
  • 3.
    What is ARC? Includesa weak reference system (Lion/iOS 5.0+) ARC code works with non-ARC code and vice versa Xcode 4.2+ only
  • 4.
    Manual Reference Counting Justto help you appreciate ARC... Retain: +1 retain count (claim ownership) Release: -1 retain count (revoke ownership) Autorelease: Ownership is transferred to latest autorelease pool on the current thread When retain count reaches 0, the object is deleted. With ARC you ignore all of this
  • 5.
    New Rules You cannotexplicitly invoke dealloc, or implement or invoke retain, release, retainCount, or autorelease. The prohibition extends to using @selector(retain), @selector(release), and so on.
  • 6.
    New Rules You mayimplement a dealloc method if you need to manage resources other than releasing instance variables. You do not have to (indeed you cannot) release instance variables, but you may need to invoke [systemClassInstance setDelegate:nil] on system classes and other code that isn’t compiled using ARC.
  • 7.
    New Rules Custom deallocmethods in ARC do not require a call to [super dealloc] (it actually results in a compiler error). The chaining to super is automated and enforced by the compiler. You can still use CFRetain, CFRelease, and other related functions with Core Foundation-style objects.
  • 8.
    New Rules You cannotuse NSAllocateObject or NSDeallocateObject. You create objects using alloc; the runtime takes care of deallocating objects. You cannot use object pointers in C structures. Rather than using a struct, you can create an Objective-C class to manage the data instead.
  • 9.
    New Rules There isno casual casting between id and void *. You must use special casts that tell the compiler about object lifetime. You need to do this to cast between Objective-C objects and Core Foundation types that you pass as function arguments.
  • 10.
    New Rules Cannot useNSAutoreleasePool objects. ARC provides @autoreleasepool blocks instead. These have an advantage of being more efficient than NSAutoreleasePool. You cannot use memory zones. There is no need to use NSZone any more—they are ignored by the modern Objective-C runtime anyway.
  • 11.
    New Rules To allowinteroperation with manual retain-release code, ARC imposes some constraints on method and variable naming: You cannot give a property a name that begins with new.
  • 12.
    New Rules Summary: ARCdoes a lot of stuff for you. Just write your code and trust ARC to do the right thing. If you write C code, then you actually have to do some work.
  • 13.
    Old way: ARC way: NSAutoreleasePool * pool = @autoreleasepool { // This is cool! [NSAutoreleasePool new]; NSArray * comps = [NSArray NSArray * comps = [NSArray arrayWithObjects:@"BYU", arrayWithObjects:@"BYU", @"CocoaHeads", nil]; @"CocoaHeads", nil]; NSString * path = [NSString NSString * path = [NSString pathWithComponents:comps]; pathWithComponents:comps]; NSURL * url = [[NSURL alloc] NSURL * url = [[NSURL alloc] initWithPath:path]; initWithPath:path]; // Do something with the URL. // Do something with the URL. [url release]; // Hey look! No release! [pool drain]; } // Automatic drain!
  • 14.
    Automatic Conversion 1.Edit >Refactor > Convert to Objective-C ARC 2.Select the files you want to convert (probably all) 3.Xcode will let you know if it can’t convert certain parts You may want to continue on errors Xcode > Preferences > General > Continue building after errors
  • 15.
  • 16.
    Weak Referencing Weak referencedoesn’t increment retain count Weak reference is nilled when the object is dealloc’d Adds some overhead due to bookkeeping Great for delegates @property(nonatomic, weak) id delegate; iOS 5.0+
  • 17.
    IBOutlets Weak reference: Strong reference: Used only with non- Must be used for top- top-level IBOutlets level IBOutlets Automatically nils May be used for non- IBOutlet in low top-level IBOutlets memory condition Manually nil IBOutlet in Requires some extra -viewDidUnload overhead
  • 18.
  • 19.
    Lifetime Qualifiers Jedi Level __strong A retained reference (default) __weak Uses weak reference system
  • 20.
    Lifetime Qualifiers Jedi Level __unsafe_unretained Unretained reference—like assign property __autoreleasing Autoreleased reference
  • 21.
    What About C? Jedi Level ARC does not manage memory for C You must call free() for every malloc() Core Foundation objects use CFRelease() Toll-free bridging requires an extra keyword
  • 22.
    Bridging Jedi Level __bridge Straight bridge cast __bridge_transfer -1 to the retain count __bridge_retained +1 to the retain count
  • 23.
    Bridging Made Easy Jedi Level The casts are hard to remember Use these macros instead: CFBridgingRetain(obj) = ARC to C CFBridgingRelease(obj) = C to ARC
  • 24.
    Disabling ARC Jedi Level ARC can be disabled on a file-level. Project file > Main target > Build phases > Compile sources > Add compiler flag “-fno-objc-arc” If ARC is not on by default, it can be turned on manually with “-fobjc-arc”
  • 25.
  • 26.
    Blocks Jedi Level // WARNING: Retain loop! // The static analyzer will warn you about this. [self setBlock:^{ [self doSomething]; [_ivar doSomethingElse]; // Implicitly self->_ivar }
  • 27.
    Blocks Jedi Level // No retain loop __block __unsafe_unretained id unretainedSelf = self; [self setBlock:^{ [unretainedSelf doSomething]; [[unretainedSelf var] doSomethingElse]; }
  • 28.
    Blocks Jedi Level // Better alternative (iOS 5.0+) __weak id weakSelf = self; [self setBlock:^{ [weakSelf doSomething]; [[weakSelf var] doSomethingElse]; }
  • 29.
    Return by Reference Jedi Level Return by reference is fairly common, especially with NSError. Example: -(BOOL)save:(NSError *__autoreleasing*)outError;
  • 30.
    Return by Reference Jedi Level // What you write NSError * error = nil; // Implicitly __strong. if (![self save:&error]) { // An error occurred. }
  • 31.
    Return by Reference Jedi Level // What ARC writes NSError * __strong error = nil; NSError * __autoreleasing tmp = error; if (![self save:&tmp]) { // An error occurred. }
  • 32.
    Return by Reference Jedi Level // This isn’t a big deal, but it avoids the temporary variable NSError * __autoreleasing error = nil; if (![self save:&error]) { // An error occurred. }
  • 33.
  • 34.
    Want to LearnMore? WWDC 2011: Session 323 Transitioning to ARC Release Notes