Sunday, July 27, 2014

Demystifying bridged cast in Objective-C

Recently as I was developing my 2D game engine on iOS, there was a need to use STL as I didn't really want to reinvent the wheel in Objective-C, especially since it's going to be phased out by Apple in favor of Swift. Inevitably I had to do some sort of casting between both worlds. The best description I came across was this one : Here , which is quite close but not very comprehensive. Now, if you don't believe me, test your knowledge by answering the questions
    id obj = [[NSObject alloc] init];
    CFTypeRef ref = (__bridge_retained CFTypeRef) obj;
    NSLog(@"CF Retain Count %ld", CFGetRetainCount(ref)); //Q1
    CFRetain(ref);
    id obj2 = (__bridge_transfer id)ref;
    ref = (__bridge_retained CFTypeRef)obj2;
    NSLog(@"CF Retain Count %ld", CFGetRetainCount(ref)); //Q2
    id obj3 = obj;
    NSLog(@"CF Retain Count %ld", CFGetRetainCount(ref)); //Q3
    id obj4 = (__bridge id)ref;
    NSLog(@"CF Retain Count %ld", CFGetRetainCount(ref)); //Q4
    //Q5 : How many CFRelease/CFBridgingRelease do we need here to release the object when it goes out of scope?
If you can't answer those, my hint is, there is indeed only 1 reference count in ObjC, whether you use the bridged cast or not.
See the cheat sheet below:
__bridge_retained = CFBridgingRetain = CFRetain + casting
__bridge_transfer = CFBridgingRelease = CFRelease + casting
__bridge : Does nothing other than casting