Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Automatic Reference Counting

Rob Brown
February 09, 2012

Automatic Reference Counting

ARC makes Objective-C development so much easier and enjoyable by eliminating almost all need to manually handle memory management.

Rob Brown

February 09, 2012
Tweet

More Decks by Rob Brown

Other Decks in Programming

Transcript

  1. 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
  2. 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
  3. 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
  4. 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.
  5. 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.
  6. 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.
  7. 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.
  8. 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.
  9. 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.
  10. 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.
  11. 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.
  12. Old way: NSAutoreleasePool * pool = [NSAutoreleasePool new]; NSArray *

    comps = [NSArray arrayWithObjects:@"BYU", @"CocoaHeads", nil]; NSString * path = [NSString pathWithComponents:comps]; NSURL * url = [[NSURL alloc] initWithPath:path]; // Do something with the URL. [url release]; [pool drain]; ARC way: @autoreleasepool { // This is cool! NSArray * comps = [NSArray arrayWithObjects:@"BYU", @"CocoaHeads", nil]; NSString * path = [NSString pathWithComponents:comps]; NSURL * url = [[NSURL alloc] initWithPath:path]; // Do something with the URL. // Hey look! No release! } // Automatic drain!
  13. 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
  14. 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+ Weak Referencing
  15. IBOutlets Weak reference: Used only with non- top-level IBOutlets Automatically

    nils IBOutlet in low memory condition Requires some extra overhead Strong reference: Must be used for top- level IBOutlets May be used for non- top-level IBOutlets Manually nil IBOutlet in -viewDidUnload
  16. What About C? 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 Jedi Level
  17. Bridging __bridge Straight bridge cast __bridge_transfer -1 to the retain

    count __bridge_retained +1 to the retain count Jedi Level
  18. Bridging Made Easy The casts are hard to remember Use

    these macros instead: CFBridgingRetain(obj) = ARC to C CFBridgingRelease(obj) = C to ARC Jedi Level
  19. Disabling ARC 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” Jedi Level
  20. Blocks // WARNING: Retain loop! // The static analyzer will

    warn you about this. [self setBlock:^{ [self doSomething]; [_ivar doSomethingElse]; // Implicitly self->_ivar } Jedi Level
  21. Blocks // No retain loop __block __unsafe_unretained id unretainedSelf =

    self; [self setBlock:^{ [unretainedSelf doSomething]; [[unretainedSelf var] doSomethingElse]; } Jedi Level
  22. Blocks // Better alternative (iOS 5.0+) __weak id weakSelf =

    self; [self setBlock:^{ [weakSelf doSomething]; [[weakSelf var] doSomethingElse]; } Jedi Level
  23. Return by Reference Return by reference is fairly common, especially

    with NSError. Example: -(BOOL)save:(NSError *__autoreleasing*)outError; Jedi Level
  24. Return by Reference // What you write NSError * error

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

    error = nil; NSError * __autoreleasing tmp = error; if (![self save:&tmp]) { // An error occurred. } Jedi Level
  26. Return by Reference // This isn’t a big deal, but

    it avoids the temporary variable NSError * __autoreleasing error = nil; if (![self save:&error]) { // An error occurred. } Jedi Level