目录
- 1 Memory Management
- Item 29:Understand Reference Counting
- Item 30:User ARC to Make Reference Counting Easier
- Item 31:Release References and Clean Up Observation State Only in dealloc
- Item 32:Beware of Memory Management with Exception-Safe Code
- Item 33:Use Weak References to Avoid Retain Cycles
- Item 34:Use Autorelease Pool Blocks to Reduce High-Memory Waterline
- Item 35:Use Zombies to Help Debug Memory-Management Problems
- Item 36:Avoid Using retainCount
- 2 Reference
1 Memory Management
Item 29:Understand Reference Counting
-
Reference-counting memory management is based on a counter that is incremented and decremented. An object is created with a count of at least 1. An object with a positive retain count is alive. When the retain count drops to 0, the object is destroyed.
-
As it goes through its life cycle, an object is retained and released by other objects holding references to it. Retaining and releasing increments and decrements the retain count respectively.
Item 30:User ARC to Make Reference Counting Easier
- Method-Naming Rules Applied by ARC.
alloc
,new
,copy
,mutableCopy
methods return an object owned by the caller method.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
+ (EOCPerson*)newPerson { EOCPerson *person = [[EOCPerson alloc] init]; return person; /** * The method name begins with 'new', and since 'person' * already has an unbalanced +1 retain count from the * 'alloc', no retains, releases, or autoreleases are * required when returning. */ } + (EOCPerson*)somePerson { EOCPerson *person = [[EOCPerson alloc] init]; return person; /** * The method name does not begin with one of the "owning" * prefixes, therefore ARC will add an autorelease when * returning 'person'. * The equivalent manual reference counting statement is: * */ } - (void)doSomething { EOCPerson *personOne = [EOCPerson newPerson]; // ... EOCPerson *personTwo = [EOCPerson somePerson]; // ... /* * At this point, 'personOne' and 'personTwo' go out of scope, therefore ARC needs to clean them up as required. * - 'personOne' was returned as owned by this block of code, so it needs to be released. * - 'personTwo' was returned not owned by this block of code, so it does not need to be released. * The equivalent manual reference counting cleanup code is: * [personOne release]; */ }
- Memory-Management Semantics of Variables.
_strong
,_unsafe_unretained
,__weak
,_autoreleasing
. - ARC Handling of Instance Variables. ARC also handles the memory management of instance variables. Doing so requires ARC to automatically generate the required cleanup code during deallocation.
1 2 3 4 5
-(void) dealloc{ [_foo release]; [_bar release]; [super dealloc]; }
- Overriding the Memory-Management Methods
Item 31:Release References and Clean Up Observation State Only in dealloc
-
The
dealloc
method should be used only to release references to other objects and to unregister anything that needs to be, such as Key-Value Observing(KVO) orNSNotificationCenter
notifications. -
If an object holds onto system resources, such as file descriptors, there should be a method for releasing these resources. It should be the contract with the consumer of such a class to call this
close
method when finished using the resources. -
Method calls should be avoided in
dealloc
methods in case those methods try to perform asynchronous work or end up assuming that the object is in a normal state, which it won’t be.
Item 32:Beware of Memory Management with Exception-Safe Code
-
When exceptions are caught, care should be taken to ensure that any required cleanup is done for objects created within the try block.
-
By default, ARC does not emit code that handles cleanup when exceptions are thrown. This can be enabled with a compiler flag but produces code that is larger and comes with a runtime cost.
Item 33:Use Weak References to Avoid Retain Cycles
-
Retain cycles can be avoided by making certain references weak.
-
Weak references may or may not be autonilling. Autonilling is a new feature introduced with ARC and is implemented in the runtime. Autonilling weak references are always safe to read, as they will never contain a reference to a deallocated object.
Item 34:Use Autorelease Pool Blocks to Reduce High-Memory Waterline
- Autoreleas pools are arranged in a stack, with an object being added to the topmost pool when it is sent the autorelease message.
- Correct application of autorelease pools can help reduce the high-memory waterline of an application.
1 2 3 4 5 6 7 8
NSArray *databaseRecords = /* ... */; NSMutableArray *people = [NSMutableArray new]; for (NSDictionary *record in databaseRecords) { @autoreleasepool { EOCPerson *person =[[EOCPerson alloc] initWithRecord:record]; [people addObject:person]; } }
- Modern autorelease pools using the new
@autoreleasepool {}
syntax are cheap.
Item 35:Use Zombies to Help Debug Memory-Management Problems
-
When an object is deallocated, it can optionally be turned into a zombie instead of being deallocated. This feature is turned on by using the envrionment flag NSZombieEnabled.
-
An object is turend into a zombie by manipulating its isa pointer to change the object’s class to a special zombie class. A zombie class responds to all selectors by aborting the application after printing a message to indicate what message was sent to what object.
Item 36:Avoid Using retainCount
-
The retain count of an object might seem useful but usually is not, because the absolute retain count at any given time does not give a complete picture of an object’s lifetime.
-
When ARC came along, the
retainCount
method was deprecated, and using it causes a compiler error to be emitted.