session 406 - adopting automatic reference counting
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
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