Wednesday, January 22, 2014

Understanding ios ARC and CFRefType

1. Why ARC does not handle CFRefType?
CFRefType basically is a "void *" type, it point to a core foundation object that handles CFRelease and CFRetain, but not retain and release as objective-c object does. So CFRefType is not managed by ARC. That is why when casting between Objective-c type and CFRefType, you need to tell ARC who owns the object.

__bridge: no ownership transfer
NSMutableString * string1 = [[NSMutableString allocinitWithFormat:@"First : %@"@"adb"];
 CFStringRef cfString = nil;
 cfString = (__bridge CFStringRef )string1;

 string1 = nil; //at this moment, cfString is also set to nil


__bridge_retained or CFBridgingRetain: transfer ownershjp of  Objective-C object to Core Foundation pointer, and need to call CFRelease to collect the object
 NSMutableString * string1 = nil;
 CFStringRef cfString = nil;
 string1 = [[NSMutableString allocinitWithFormat:@"First Name: %@"@"adb"];
 cfString = (__bridge_retained CFStringRef )string1;

 string1 = nil//at this moment, cfString is still hold the original string, as it has been retained

__bridge_transfer or CFBridgingRelease: transfer ownership of core foundation object to ARC, ARC will release the object when it is no longer referenced
NSMutableString * string1 = nil;
 CFStringRef cfString = CFSTR("Hello, world.");;
 string1 = (__bridge_transfer NSMutableString*)cfString;
 CFRelease(cfString); //at this moment string1 still hold the valid string data

2. Ownership transfer for Objective C property and variable for ARC
When assigning values to objective c property or variable, it implies the ownership transferring, the receiver either become the owner of the assigned object or not depending on the variable qualifier:
__strong: the receiver becomes the new owner. (default)
__weak: the receiver is not the owner, and the object may become nil anytime
__unsafe_unretained: the receive is not the owner, and not set to nil if the object is deleted.
__autoreleasing: the receiver is retained and autoreleased.  is usually used for declaring by reference  parameter, it should always used within an autorelease. Most of time, the arced object is released when the variable is set to nil or the variable is out of definition scope. __autoleasing will allow to collect an object when the thread ends or the autorelease pool close, so it uses thread instead of variable scope to control the object's life time.

3. CFRefType ownership transfer
If a method contains copy or create and return a CFRefType object, then it transfers the ownership to caller, and caller needs to CFRelease it.

4. Objective C ownership transfer
If the object transfer the ownership to caller and needs ARC to release the object, then the method needs to start with alloc, copy, mutableCopy or new. Otherwise, ARC will not collect it when it is no longer referred.

5. id and void*
id represents an Objective C object, which responds to retain and release method, while void * is just an memory blob.  A lot of objective C API accepts id as parameter, but not void*, so void* cannot be cast as id.



No comments:

Post a Comment