session 406 - adopting automatic reference counting

Upload: foufoutos73

Post on 03-Apr-2018

231 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    1/180

    These are confidential sessionsplease refrain from streaming, blogging, or taking pictures

    Session 406 / 416

    Malcolm CrawfordTechnical Writer

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    2/180

    Manual memory management

    What is ARC?

    How does it work? How do you switch?

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    3/180

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    4/180

    Memory management problems lead to crashing

    Crashing leads to unhappiness

    Unhappiness leads to rejection

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    5/180

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    6/180

    Reason for apps

    crashing

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    7/180

    Cause of app

    rejection

    Reason for apps

    crashing

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    8/180

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    9/180

    What were the problemswith traditional Objective-Cmemory management?

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    10/180

    Straightforward rules, but

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    11/180

    Straightforward rules, but

    Lots of details

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    12/180

    Straightforward rules, but

    Lots of details Naming conventions

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    13/180

    Straightforward rules, but

    Lots of details Naming conventions

    Autorelease pools

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    14/180

    Straightforward rules, but

    Lots of details Naming conventions

    Autorelease pools

    Block_copy

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    15/180

    Straightforward rules, but

    Lots of details Naming conventions

    Autorelease pools

    Block_copy

    Autoreleasing or not?

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    16/180

    Straightforward rules, but

    Lots of details Naming conventions

    Autorelease pools

    Block_copy

    Autoreleasing or not?

    [NSString stringWith

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    17/180

    Straightforward rules, but

    Lots of details Naming conventions

    Autorelease pools

    Block_copy

    Autoreleasing or not?

    [NSString stringWith

    [[NSString alloc] initWith ]

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    18/180

    Straightforward rules, but

    Lots of details Naming conventions

    Autorelease pools

    Block_copy

    Autoreleasing or not?

    [NSString stringWith

    [[NSString alloc] initWith ]

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    19/180

    Never forget the rules

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    20/180

    Never forget the rules

    Never forget a release on anerror case

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    21/180

    Never forget the rules

    Never forget a release on anerror case

    Never dereference adangling pointer

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    22/180

    Never forget the rules

    Never forget a release on anerror case

    Never dereference adangling pointer

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    23/180

    Even with help from tools

    Instruments Allocations, Leaks, Zombies

    Static Analyzer

    Heap

    ObjectAlloc

    vmmap

    MallocScribble

    Debugger watchpoints and lots more

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    24/180

    Tells you when you did not follow the rules

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    25/180

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    26/180

    Dozens or hundreds of leaksare common

    Developers think the analyzer

    is buggy

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    27/180

    Dozens or hundreds of leaksare common

    Developers think the analyzer

    is buggy Common sources of false positives:

    Core Foundation APIs

    Unions, structs, etc.

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    28/180

    Dozens or hundreds of leaksare common

    Developers think the analyzer

    is buggy Common sources of false positives:

    Core Foundation APIs

    Unions, structs, etc.

    Cocoa code has strong patterns Naming conventions

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    29/180

    Tells you when you did not follow the rules

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    30/180

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    31/180

    ARC formalizes conventions,

    automates the rules

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    32/180

    ARC formalizes conventions,

    automates the rules

    what compilers are best at

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    33/180

    Simpler, safer through automation

    Object-Oriented C

    Retain Counting

    Properties

    Blocks

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    34/180

    Simpler, safer through automation

    Object-Oriented C

    Retain Counting

    Properties

    Blocks

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    35/180

    Simpler, safer through automation

    Object-Oriented C

    Retain Counting

    Properties

    Blocks

    ARC

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    36/180

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    37/180

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    38/180

    Automatic memory management of Objective-C objects Compiler obeys and enforces existing conventions

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    39/180

    Automatic memory management of Objective-C objects Compiler obeys and enforces existing conventions

    Full interoperability with manual retain and release

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    40/180

    Automatic memory management of Objective-C objects Compiler obeys and enforces existing conventions

    Full interoperability with manual retain and release

    New runtime features: Weak pointers

    Advanced performance optimizations

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    41/180

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    42/180

    No new runtime memory model

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    43/180

    No new runtime memory model

    No automation for malloc/free, CF, etc.

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    44/180

    No new runtime memory model

    No automation for malloc/free, CF, etc.

    No garbage collector No heap scans

    No whole app pauses

    No non-deterministic releases

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    45/180

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    46/180

    Compiler adds retain/release/autorelease for you

    - (NSString*)greeting {

    return [[NSString alloc] initWithFormat:@"Hi %@", bloke.name];

    }

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    47/180

    Compiler adds retain/release/autorelease for you

    - (NSString*)greeting {

    return [[[NSString alloc] initWithFormat:@"Hi %@", bloke.name] autorelease];

    }

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    48/180

    Compiler adds retain/release/autorelease for you

    - (NSString*)greeting {

    return [NSString stringWithFormat:@"Hi %@", bloke.name];

    }

    - (NSString*)greeting {

    return [[[NSString alloc] initWithFormat:@"Hi %@", bloke.name] autorelease];

    }

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    49/180

    Compiler adds retain/release/autorelease for you

    - (NSString*)greeting {

    return [NSString stringWithFormat:@"Hi %@", bloke.name];

    }

    Different APIs that achieve same result have same cognitive load

    - (NSString*)greeting {

    return [[[NSString alloc] initWithFormat:@"Hi %@", bloke.name] autorelease];

    }

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    50/180

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    51/180

    Project setting in Xcode

    Objective-C Automatic Reference Counting Yes

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    52/180

    Project setting in Xcode

    New projects default to ARC

    Objective-C Automatic Reference Counting Yes

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    53/180

    Project setting in Xcode

    New projects default to ARC

    Existing code must migrate to ARC

    Objective-C Automatic Reference Counting Yes

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    54/180

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    55/180

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    56/180

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    57/180

    Manual Reference Counting Automatic Reference Counting

    dispatch_block_t getfoo(int i) {return [[^{

    print(i); } copy] autorelease];}

    dispatch_block_t getfoo(int i) {return ^{

    print(i); };}

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    58/180

    Problem: Cannot rely on heuristics

    Like the static analyzer does

    Solution: Formalize and automate best practice

    Four new rules

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    59/180

    Problem: Cannot rely on heuristics

    Like the static analyzer does

    Solution: Formalize and automate best practice

    Four new rules

    Enforced by the compiler

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    60/180

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    61/180

    Memory management is part ofthe language

    Cannot call retain/release/autorelease

    Cannot implement these methods

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    62/180

    Memory management is part ofthe language

    Cannot call retain/release/autorelease

    Cannot implement these methods

    SolutionsThe compiler takes care of it

    NSObject performance optimizations

    Better patterns for singletons

    while ([x retainCount] != 0)

    [x release];

    Broken code, Anti-pattern

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    63/180

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    64/180

    struct Pair {

    NSString *Name; // retained

    int Value;

    };

    Pair *P = malloc(...);

    ...

    ...

    free(P); // Must drop references

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    65/180

    Compiler must know when references come and go Pointers must be zero initialized

    Release when reference goes away

    struct Pair {

    NSString *Name; // retained

    int Value;

    };

    Pair *P = malloc(...);

    ...

    ...

    free(P); // Must drop references

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    66/180

    Compiler must know when references come and go Pointers must be zero initialized

    Release when reference goes away

    Solution: Just use objects Better tools support

    Best practice for Objective-C

    struct Pair {

    NSString *Name; // retained

    int Value;

    };

    Pair *P = malloc(...);

    ...

    ...

    free(P); // Must drop references

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    67/180

    Compiler must know whether void* is retained

    New APIs cast between Objective-C and Core Foundation-style objectsCFStringRef W = (__bridge CFStringRef)A;

    NSString *X = (__bridge NSString *)B;CFStringRef Y = (CFStringRef)CFBridgingRetain(obj);

    NSString *Z = (NSString *)CFBridgingRelease(ref);

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    68/180

    Compiler must know whether void* is retained

    New APIs cast between Objective-C and Core Foundation-style objectsCFStringRef W = ( CFStringRef)A;

    NSString *X = ( NSString *)B;CFStringRef Y = ( CFStringRef)C;

    NSString *Z = ( NSString *)D;

    __bridge

    __bridge__bridge_retain

    __bridge_transfer

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    69/180

    Compiler must reason about autoreleased pointers

    NSAutoreleasePool not a real objectcannot be retainedint main(int argc, char *argv[]) {

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];int retVal = UIApplicationMain(argc, argv, nil, nil);

    [pool release];

    return retVal;

    }

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    70/180

    Compiler must reason about autoreleased pointers

    NSAutoreleasePool not a real objectcannot be retainedint main(int argc, char *argv[]) {

    @autoreleasepool {return UIApplicationMain(argc, argv, nil, nil);

    }

    }

    Works even without ARC

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    71/180

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    72/180

    Think about ownership Strong references keep objects alive

    Objects deallocated when no more strong references remain

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    73/180

    Think about ownership Strong references keep objects alive

    Objects deallocated when no more strong references remain

    Think about your object graph

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    74/180

    Think about ownership Strong references keep objects alive

    Objects deallocated when no more strong references remain

    Think about your object graph

    Stop thinking about retain/release/autorelease

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    75/180

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    76/180

    Safe, nonretaining reference Drop to nil automatically

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    77/180

    Safe, nonretaining reference Drop to nil automatically

    Now supported in ARC:@property (weak) NSView *myView; // property attribute

    id __weak myObject; // variable keyword

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    78/180

    Like before, cycles cause leaks in ARC

    Standard patterns still work Set property values to nil

    Use weak references

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    79/180

    No performance difference frommanual memory management

    Peak memory high water

    mark lower No GC overhead

    No delayed deallocations

    No app pauses, no nondeterminism

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    80/180

    Simplified memory managementmodel

    Easier to learn

    More productive Easier to maintain

    Safer and more stable

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    81/180

    Simplified memory managementmodel

    Easier to learn

    More productive Easier to maintain

    Safer and more stable

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    82/180

    Dave ZarzyckiRuntime Team

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    83/180

    Lots of rules and conventions

    High hurdles for new developers

    Constant attention for existing

    developers Requires perfection

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    84/180

    @implementation Stack { NSMutableArray *_array; }

    - (id) init {

    if (self = [super init])

    _array = [NSMutableArray array];

    return self;

    }- (void) push: (id) x {

    [_array addObject: x];

    }

    - (id) pop {

    id x = [_array lastObject];

    [_array removeLastObject];

    return x;}

    @end

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    85/180

    @implementation Stack { NSMutableArray *_array; }

    - (id) init {

    if (self = [super init])

    _array = [[NSMutableArray array] retain];

    return self;

    }- (void) push: (id) x {

    [_array addObject: x];

    }

    - (id) pop {

    id x = [_array lastObject];

    [_array removeLastObject];

    return x;}

    @end

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    86/180

    This array is autoreleasedSystem will deallocate it outfrom under us

    @implementation Stack { NSMutableArray *_array; }

    - (id) init {

    if (self = [super init])

    _array = [[NSMutableArray array] retain];

    return self;

    }- (void) push: (id) x {

    [_array addObject: x];

    }

    - (id) pop {

    id x = [_array lastObject];

    [_array removeLastObject];

    return x;}

    @end

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    87/180

    @implementation Stack { NSMutableArray *_array; }

    - (id) init {

    if (self = [super init])

    _array = [[NSMutableArray array] retain];

    return self;

    }- (void) push: (id) x {

    [_array addObject: x];

    }

    - (id) pop {

    id x = [_array lastObject];

    [_array removeLastObject];

    return x;}

    @end

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    88/180

    @implementation Stack { NSMutableArray *_array; }

    - (id) init {

    if (self = [super init])

    _array = [[NSMutableArray array] retain];

    return self;

    }- (void) push: (id) x {

    [_array addObject: x];

    }

    - (id) pop {

    id x = [_array lastObject];

    [_array removeLastObject];

    return x;}

    @end- (void) dealloc { [_array release]; [super dealloc]; }

    @end

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    89/180

    Now it is leakedNeed a dealloc method

    @implementation Stack { NSMutableArray *_array; }

    - (id) init {

    if (self = [super init])

    _array = [[NSMutableArray array] retain];

    return self;

    }- (void) push: (id) x {

    [_array addObject: x];

    }

    - (id) pop {

    id x = [_array lastObject];

    [_array removeLastObject];

    return x;}

    @end- (void) dealloc { [_array release]; [super dealloc]; }

    @end

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    90/180

    @implementation Stack { NSMutableArray *_array; }

    - (id) init {

    if (self = [super init])

    _array = [[NSMutableArray array] retain];

    return self;

    }- (void) push: (id) x {

    [_array addObject: x];

    }

    - (id) pop {

    id x = [_array lastObject];

    [_array removeLastObject];

    return x;}

    - (void) dealloc { [_array release]; [super dealloc]; }

    @end

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    91/180

    This might invalidate xWorks only if there are other

    references to it

    @implementation Stack { NSMutableArray *_array; }

    - (id) init {

    if (self = [super init])

    _array = [[NSMutableArray array] retain];

    return self;

    }- (void) push: (id) x {

    [_array addObject: x];

    }

    - (id) pop {

    id x = [_array lastObject];

    [_array removeLastObject];

    return x;}

    - (void) dealloc { [_array release]; [super dealloc]; }

    @end

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    92/180

    @implementation Stack { NSMutableArray *_array; }

    - (id) init {

    if (self = [super init])

    _array = [[NSMutableArray array] retain];

    return self;

    }- (void) push: (id) x {

    [_array addObject: x];

    }

    - (id) pop {

    id x = [[_array lastObject] retain];

    [_array removeLastObject];

    return x;}

    - (void) dealloc { [_array release]; [super dealloc]; }

    @end

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    93/180

    @implementation Stack { NSMutableArray *_array; }

    - (id) init {

    if (self = [super init])

    _array = [[NSMutableArray array] retain];

    return self;

    }- (void) push: (id) x {

    [_array addObject: x];

    }

    - (id) pop {

    id x = [[_array lastObject] retain];

    [_array removeLastObject];

    return x;}

    - (void) dealloc { [_array release]; [super dealloc]; }

    @end

    [x autorelease];

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    94/180

    Now were returning aretained pointerViolates convention;

    probably a leak

    @implementation Stack { NSMutableArray *_array; }

    - (id) init {

    if (self = [super init])

    _array = [[NSMutableArray array] retain];

    return self;

    }- (void) push: (id) x {

    [_array addObject: x];

    }

    - (id) pop {

    id x = [[_array lastObject] retain];

    [_array removeLastObject];

    return x;}

    - (void) dealloc { [_array release]; [super dealloc]; }

    @end

    [x autorelease];

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    95/180

    @implementation Stack { NSMutableArray *_array; }

    - (id) init {

    if (self = [super init])

    _array = [[NSMutableArray array] retain];

    return self;

    }- (void) push: (id) x {

    [_array addObject: x];

    }

    - (id) pop {

    id x = [[_array lastObject] retain];

    [_array removeLastObject];

    return [x autorelease];}

    - (void) dealloc { [_array release]; [super dealloc]; }

    @end

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    96/180

    Write code naturally

    Break cycles when necessary

    Stop worrying about retains

    Write great apps

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    97/180

    Automates what programmers do anyway

    Applies local rules

    Guarantees local correctness

    Optimizes away redundancies

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    98/180

    Objective-C, block pointers

    Locals, globals, parameters, instance variables

    Four different kinds of ownership

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    99/180

    Default for all variables

    Like a retain property

    NSString *name;

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    100/180

    __strong NSString *name;

    Default for all variables

    Like a retain property

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    101/180

    Implicitly initialized to nil

    Safer for ARC-generated code Safer for your code

    NSString *name;

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    102/180

    NSString *name = nil;

    Implicitly initialized to nil

    Safer for ARC-generated code Safer for your code

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    103/180

    Current value is implicitly released

    All variables, even ivars

    if (i < 10) {

    NSString *name = ...;

    }

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    104/180

    if (i < 10) {

    NSString *name = ...;

    [name release];

    }

    Current value is implicitly released

    All variables, even ivars

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    105/180

    Nothing special for reads

    For writes: Retain the new value

    Release the old value

    name = newName;

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    106/180

    [newName retain];

    NSString *oldName = name;

    name = newName;

    [oldName release];

    Nothing special for reads

    For writes: Retain the new value

    Release the old value

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    107/180

    Describes out-parameters

    Only on the stack

    Not for general use

    - (void) runWithError:

    (NSError **) err {

    if (!valid_)

    *err = ...;

    }

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    108/180

    - (void) runWithError:

    (__autoreleasingNSError **) err {

    if (!valid_)

    *err = [[...retain] autorelease];

    }

    Describes out-parameters

    Only on the stack

    Not for general use

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    109/180

    Like a traditional variable, or an assign property

    Not initialized No extra logic

    No restrictions

    Useful in global structs with constant @ strings

    __unsafe_unretained NSString *unsafeName = name;

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    110/180

    Runtime manages reads and writes

    Becomes nil as soon as object starts deallocation

    __weak NSString *weakName = name;

    char c = [weakName

    characterAtIndex: 0];

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    111/180

    __weak NSString *weakName = nil;

    objc_storeWeak(&weakName, name);

    char c = [objc_readWeak(&weakName)

    characterAtIndex: 0];

    objc_storeWeak(&weakName, nil);

    Runtime manages reads and writes

    Becomes nil as soon as object starts deallocation

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    112/180

    Does this transfer ownership?

    Return values can be returned retained

    Similar concepts for other transfers into or out of ARC

    Decided by method family

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    113/180

    Naming convention

    First word in first part of selector

    alloc, copy, init, mutableCopy, new transfer ownership

    Everything else does not

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    114/180

    No transfer

    Retain immediately

    Autorelease after leaving all scopes

    - (NSString*) serial {

    return _serial;

    }

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    115/180

    - (NSString*) serial {

    NSString *returnValue

    = [_serialretain];

    return[returnValue autorelease];

    }

    No transfer

    Retain immediately

    Autorelease after leaving all scopes

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    116/180

    Passes back ownership

    Like a normal return without the autorelease

    - (NSString*) newSerial {

    return _serial;

    }

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    117/180

    - (NSString*) newSerial {

    NSString *returnValue

    = [_serialretain];

    returnreturnValue;

    }

    Passes back ownership

    Like a normal return without the autorelease

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    118/180

    Takes ownership

    Return value released at end of statement

    - (void) logSerial {

    NSLog(%@\n, [self newSerial]);

    ...

    }

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    119/180

    - (void) logSerial {

    NSString *returnValue

    = [self newSerial];

    NSLog(%@\n,returnValue);

    [returnValue release]; ...

    }

    Takes ownership

    Return value released at end of statement

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    120/180

    - (id) init {

    if (self = [super init])

    _array = [NSMutableArray array];

    return self;

    }

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    121/180

    - (id) init {

    if (self = [super init]) {

    NSMutableArray *oldArray = _array;

    _array =[[NSMutableArray array]

    retain]; [oldArray release];

    }

    return self;

    }

    - (void) dealloc {

    [_array release];[super dealloc];

    }

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    122/180

    - (id) pop {

    id x = [_array lastObject];

    [_array removeLastObject];

    return x;

    }

    Local rules make this work

    Unnecessary retain/release are optimized away

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    123/180

    - (id) pop {

    id x = [_array lastObject];

    [_array removeLastObject];

    id result = [xretain];

    return[result autorelease];}

    Local rules make this work

    Unnecessary retain/release are optimized away

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    124/180

    - (id) pop {

    id x = [_array lastObject];

    [_array removeLastObject];

    id result = [xretain];

    return[result autorelease];}

    - (id) pop {

    id x = [[_array lastObject]retain];

    [_array removeLastObject];

    id result = [x retain];

    [x release]; return [result autorelease];

    }

    Local rules make this work

    Unnecessary retain/release are optimized away

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    125/180

    - (id) pop {

    id x = [_array lastObject];

    [_array removeLastObject];

    id result = [xretain];

    return[result autorelease];}

    - (id) pop {

    id x = [[_array lastObject]retain];

    [_array removeLastObject];

    id result = [x retain];

    [x release]; return [result autorelease];

    }

    - (id) pop {

    id x = [[_array lastObject] retain];

    [_array removeLastObject];

    id result = [x retain];

    [x release]; return [result autorelease];

    }

    Local rules make this work

    Unnecessary retain/release are optimized away

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    126/180

    - (id) pop {

    id x = [_array lastObject];

    [_array removeLastObject];

    id result = [xretain];

    return[result autorelease];}

    - (id) pop {

    id x = [[_array lastObject]retain];

    [_array removeLastObject];

    id result = [x retain];

    [x release]; return [result autorelease];

    }

    - (id) pop {

    id x = [[_array lastObject] retain];

    [_array removeLastObject];

    id result = [x retain];

    [x release]; return [result autorelease];

    }

    - (id) pop {

    id x = [[_array lastObject] retain];

    [_array removeLastObject];

    return [x autorelease];

    }

    Local rules make this work

    Unnecessary retain/release are optimized away

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    127/180

    @implementation Stack { NSMutableArray *_array; }

    - (id) init {

    if (self = [super init])

    _array = [NSMutableArray array];

    return self;

    }- (void) push: (id) x {

    [_array addObject: x];

    }

    - (id) pop {

    id x = [_array lastObject];

    [_array removeLastObject];

    return x;

    }@end

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    128/180

    ARC follows the conventions for you

    Stop worrying about retains

    Focus on making great apps

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    129/180

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    130/180

    Overview

    Migration Steps

    Common Issues

    Deployment Options

    Demo

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    131/180

    Compile your code with the latest LLVM compiler (3.0 or later)

    Use Convert to Objective-C ARC command in Xcode

    Fix issues until everything compiles

    Migration tool then modifies your code and project

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    132/180

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    133/180

    Supported in Xcode 4.2

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    134/180

    Supported in Xcode 4.2

    Makes your source ARC compatible Removes all calls to retain,

    release, autorelease Replaces NSAutoreleasePool with@autoreleasepool

    @property(assign) becomes@property(weak) for objectpointers

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    135/180

    Analysis Migration problems presented as compile errors

    Fix errors, run analysis again

    Conversion After successful analysis, changes automatically applied

    Turns on the ARC build setting in Xcode

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    136/180

    Missing method declarations

    @interface WHImageViewController : UIViewController@property (nonatomic, readonly) NSString *identifier;@end

    - (void)pushViewControllerWithIdentifier:(NSString *)identifieranimated:(BOOL)animated {

    UIViewController *viewController;viewController = [[WHImageViewController alloc]

    initWithIdentifier:identifier];

    [self pushViewController:viewController animated:animated];

    [viewController release];

    }

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    137/180

    Missing method declarations

    @interface WHImageViewController : UIViewController@property (nonatomic, readonly) NSString *identifier;@end

    - (void)pushViewControllerWithIdentifier:(NSString *)identifieranimated:(BOOL)animated {

    UIViewController *viewController;viewController = [[WHImageViewController alloc]

    initWithIdentifier:identifier];

    [self pushViewController:viewController animated:animated];

    [viewController release];}

    Receiver type 'WHImageViewController' for instance messagedoes not declare a method with selector 'initWithIdentifier:'

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    138/180

    Unstructured Autorelease Pools

    - (void)encodeFile {/* setup */BOOL done = NO, shouldDrain = NO;NSAutoreleasePool *loopPool = [NSAutoreleasePool new];while (!done) {/* part A. */

    if (shouldDrain) {[loopPool drain];loopPool = [NAutoreleasePool new];

    } /* part B. */}[loopPool drain];

    }

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    139/180

    Unstructured Autorelease Pools

    - (void)encodeFile {/* setup */BOOL done = NO, shouldDrain = NO;NSAutoreleasePool *loopPool = [NSAutoreleasePool new];

    while (!done) {/* part A. */if (shouldDrain) {[loopPool drain];loopPool = [NAutoreleasePool new];

    } /* part B. */}[loopPool drain];

    }

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    140/180

    Unstructured Autorelease Pools

    - (void)encodeFile {/* setup */BOOL done = NO, shouldDrain = NO;NSAutoreleasePool *loopPool = [NSAutoreleasePool new];

    while (!done) {/* part A. */if (shouldDrain) {[loopPool drain];loopPool = [NAutoreleasePool new];

    } /* part B. */}[loopPool drain];

    }

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    141/180

    Unstructured Autorelease Pools

    - (void)encodeFile {/* setup */BOOL done = NO, shouldDrain = NO;NSAutoreleasePool *loopPool = [NSAutoreleasePool new];

    while (!done) {/* part A. */if (shouldDrain) {[loopPool drain];loopPool = [NAutoreleasePool new];

    } /* part B. */}[loopPool drain];

    }

    'NSAutoreleasePool' is unavailable: not available inautomatic reference counting mode

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    142/180

    Block-structured @autoreleasepool

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    143/180

    Block-structured @autoreleasepool

    - (void)encodeFile {/* setup */BOOL done = NO;while (!done) {

    @autoreleasepool {/* part A. */

    /* part B. */ } }}

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    144/180

    Block-structured @autoreleasepool

    - (void)encodeFile {/* setup */BOOL done = NO;while (!done) {

    @autoreleasepool {/* part A. */

    /* part B. */ } }}

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    145/180

    Block-structured @autoreleasepool

    - (void)encodeFile {/* setup */BOOL done = NO;while (!done) {

    @autoreleasepool {/* part A. */

    /* part B. */ } }}

    Empty @autoreleasepool on Lion is 6x faster than Snow Leopard

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    146/180

    Declarations after case labels- (void)decide {switch (currentState) {case INITIAL_STATE:;

    NSDate *date = [NSDate date];NSLog(@"started at %@", date);break;

    case MIDDLE_STATE:/* */case FINAL_STATE:/* date is in-scope here */break;

    }}

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    147/180

    Declarations after case labels- (void)decide {switch (currentState) {case INITIAL_STATE:;

    NSDate *date = [NSDate date];NSLog(@"started at %@", date);break;

    case MIDDLE_STATE:

    /* */case FINAL_STATE:/* date is in-scope here */break;

    }}

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    148/180

    Declarations after case labels- (void)decide {switch (currentState) {case INITIAL_STATE:;

    NSDate *date = [NSDate date];NSLog(@"started at %@", date);break;

    case MIDDLE_STATE:

    /* */case FINAL_STATE:/* date is in-scope here */break;

    }}

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    149/180

    Declarations after case labels- (void)decide {switch (currentState) {case INITIAL_STATE:;

    NSDate *date = [NSDate date];NSLog(@"started at %@", date);break;

    case MIDDLE_STATE:

    /* */case FINAL_STATE:/* date is in-scope here */break;

    }}

    Switch case is in protected scope

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    150/180

    Declarations after case labels require curly braces- (void)decide {switch (currentState) {case INITIAL_STATE:

    { NSDate *date = [NSDate date]; NSLog(@"started at %@", date);

    break; }/* */case FINAL_STATE:/* date is in-scope here */break;

    }}

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    151/180

    Singleton pattern/* Shared Network Activity Indicator */

    @interface ActivityIndicator : NSObject {int count;

    }

    + (ActivityIndicator *)sharedIndicator;- (void)show;

    - (void)hide;@end

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    152/180

    Overriding retain/release/autorelease@implementation ActivityIndicator

    - (id)retain { return self; }- (oneway void)release {}- (id)autorelease { return self; }- (NSUInteger) retainCount

    { return NSUIntegerMax; }

    + (ActivityIndicator *)sharedIndicator {...}

    @end

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    153/180

    Overriding retain/release/autorelease@implementation ActivityIndicator

    - (id)retain { return self; }- (oneway void)release {}- (id)autorelease { return self; }- (NSUInteger) retainCount

    { return NSUIntegerMax; }

    + (ActivityIndicator *)sharedIndicator {...}

    @end

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    154/180

    Overriding retain/release/autorelease@implementation ActivityIndicator

    - (id)retain { return self; }- (oneway void)release {}- (id)autorelease { return self; }- (NSUInteger) retainCount

    { return NSUIntegerMax; }

    + (ActivityIndicator *)sharedIndicator {...}

    @end

    ARC forbids implementation of retain

    ARC forbids implementation of release

    ARC forbids implementation of autorelease

    ARC forbids implementation of retainCount

    ARC forbids these overrides

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    155/180

    Overriding +allocWithZone:

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    156/180

    Overriding +allocWithZone:@implementation ActivityIndicator

    + (id)allocWithZone:(NSZone *)zone {static id sharedInstance;if (sharedInstance == nil)sharedInstance = [super allocWithZone:NULL];

    return sharedInstance;}

    + (ActivityIndicator *)sharedIndicator {...}

    @end

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    157/180

    Overriding +allocWithZone:@implementation ActivityIndicator

    + (id)allocWithZone:(NSZone *)zone {static id sharedInstance;if (sharedInstance == nil)sharedInstance = [super allocWithZone:NULL];

    return sharedInstance;}

    + (ActivityIndicator *)sharedIndicator {...}

    @end

    init method will have to guard against multiple calls on the

    shared instance

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    158/180

    Use simple shared instance method@implementation ActivityIndicator

    + (ActivityIndicator *)sharedIndicator {static ActivityIndicator *sharedIndicator;if (sharedIndicator == nil) sharedIndicator = [ActivityIndicator new];return sharedIndicator;

    }

    - (void)show {...}- (void)hide {...}

    @end

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    159/180

    Use dispatch_once for thread-safety@implementation ActivityIndicator

    + (ActivityIndicator *)sharedIndicator {static ActivityIndicator *sharedIndicator;static dispatch_once_t done;dispatch_once(&done, ^{ sharedIndicator = [ActivityIndicator new]; });

    return sharedIndicator;

    }- (void)show {...}

    - (void)hide {...}

    @end

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    160/180

    Classes are singletons

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    161/180

    Classes are singletons@implementation ActivityIndicator

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    162/180

    Classes are singletons@implementation ActivityIndicator

    static NSInteger count;

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    163/180

    Classes are singletons@implementation ActivityIndicator

    static NSInteger count;

    + (void)show {if (count++ == 0)

    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;}

    + (void)hide {if (count && --count == 0)[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;

    }

    @end

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    164/180

    Delegate pattern@protocol PageViewDelegate;

    @interface PageView : NSView {id delegate;/* ... */

    }

    @property(assign) id delegate;

    @end

    @implementation PageView

    @synthesize delegate;

    /* ... */

    @end

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    165/180

    Assign migrates to weak@protocol PageViewDelegate;

    @interface PageView : NSView { __weak id delegate;/* ... */

    }

    @property(weak) id delegate;

    @end

    @implementation PageView

    @synthesize delegate;

    /* ... */

    @end

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    166/180

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    167/180

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    168/180

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    169/180

    ARC is really successful No heap scans

    No whole app pauses

    No non-deterministic releases

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    170/180

    ARC is really successful No heap scans

    No whole app pauses

    No non-deterministic releases

    ARC matches our framework semantics

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    171/180

    ARC is really successful No heap scans

    No whole app pauses

    No non-deterministic releases

    ARC matches our framework semantics

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    172/180

    ARC Migration with Xcode 4.5

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    173/180

    Simpler and safer through automation

    Object-Oriented C

    Retain and Release

    Properties

    Blocks ARC

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    174/180

    Michael JurewitzDeveloper Tools Evangelist

    [email protected]

    Programming with ARC Release Noteshttp://developer.apple.com

    Apple Developer Forumshttp://devforums.apple.com

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    175/180

    Modern Objective-C PresidioWednesday 10:15AM

    Whats New in LLVM Pacific HeightsThursday 9:00AM

    Migrating to Modern Objective-C Nob HillThursday 3:15PM

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    176/180

    ObjectiveC and Automatic Reference Counting Lab Developer Tools Lab AWednesday 2:00PM

    ObjectiveC and Automatic Reference Counting Lab Developer Tools Lab CThursday 2:00PM

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    177/180

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    178/180

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    179/180

  • 7/28/2019 Session 406 - Adopting Automatic Reference Counting

    180/180