1.18. Typecasting with Automatic Reference Counting

Problem

You want to know how to use new typecasting facilities under Automatic Reference Counting in order to avoid memory leaks when working with Core Foundation objects inside your Objective-C code.

Solution

Use the __bridge, __bridge_transfer, and __bridge_retained typecasting specifiers.

Discussion

Typecasting is the process of pointing one value of type A to another value of type B. For instance, if you have a Core Foundation string object of type CFStringRef and you would like to place it inside an Objective-C string of type NSString, you can easily create an error:

- (BOOL)            application:(UIApplication *)application
  didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{

  CFStringRef coreFoundationString =
  CFStringCreateWithCString(CFAllocatorGetDefault(),
                            "C String",
                            kCFStringEncodingUTF8);

  /* Compile time error!!! */
  NSString *objCString = coreFoundationString;

  self.window = [[UIWindow alloc] initWithFrame:
                 [[UIScreen mainScreen] bounds]];

  self.window.backgroundColor = [UIColor whiteColor];
  [self.window makeKeyAndVisible];
  return YES;
}

Here we are assigning the value of the Core Foundation string coreFoundationString to the Objective-C string of type NSString named objCString, our compiler will get confused because it doesn’t know what we are intending to do with the memory assigned to each one of these objects. Additionally, we will end up with a memory leak because the compiler doesn’t know how to get rid of the Core Foundation object for us automatically. Remember that Automatic Reference Counting does not work for Core Foundation objects, so we need to assist the compiler. To do this, let’s try to understand what each one of these typecasting specifiers does:

__bridge

Simply typecasts the object on the right side of the equation to the left side. This will not modify the retain count on any of the objects; neither the one on the left nor the one on the right side of the equation.

__bridge_transfer

This typecast will assign the object on the right side to the object on the left and will release the object on the right side. So if you have a Core Foundation string, like the one we saw before, that you have just created and want to place it inside a local variable of type NSString (local variables are by default strong, see Recipe 1.17), then you should use this typecasting option because then you wouldn’t have to release the Core Foundation string after the assignment. We will see an example of this soon.

__bridge_retained

This is similar to the __bridge_transfer typecast, but will retain the object on the right side of the equation as well.

Let’s try to fix the example code we saw before. Our goal is to place the Core Foundation string into an instance of NSString (strong, by default) and then automatically release the Core Foundation string. To do this, we must use the __bridge_transfer typecasting option:

- (BOOL)            application:(UIApplication *)application
  didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{

  CFStringRef coreFoundationString =
  CFStringCreateWithCString(CFAllocatorGetDefault(),
                            "C String",
                            kCFStringEncodingUTF8);

  /* Compile time error!!! */
  NSString *objCString = (__bridge_transfer NSString *)coreFoundationString;

  NSLog(@"String = %@", objCString);

  self.window = [[UIWindow alloc] initWithFrame:
                 [[UIScreen mainScreen] bounds]];

  self.window.backgroundColor = [UIColor whiteColor];
  [self.window makeKeyAndVisible];
  return YES;
}

What happened here was that we created a new Core Foundation object. The retain count on this object is 1 at this time. Then we typecasted and assigned it, using the __bridge_transfer typecast option, to a strong local variable of type NSString. But this time, because the compiler sees the typecasting, it will retain the Core Foundation string and place it inside the local variable (since the local variable is strong by default) and after the assignment, will release the Core Foundation string. Perfect! Exactly what we wanted.

Now let’s have a look at when we would use __bridge_retained. This typecasting option is used whenever we would like the object on the right side of the equation to still exist after the assignment. Here is an example:

- (BOOL)            application:(UIApplication *)application
  didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{

  CFStringRef coreFoundationString =
  CFStringCreateWithCString(CFAllocatorGetDefault(),
                            "C String",
                            kCFStringEncodingUTF8);

  id unknownObjectType = (__bridge id)coreFoundationString;

  CFStringRef anotherString = (__bridge_retained CFStringRef)unknownObjectType;

  NSString *objCString = (__bridge_transfer NSString *)coreFoundationString;
  NSLog(@"String = %@", objCString);
  objCString = nil;

  CFRelease(anotherString);

  self.window = [[UIWindow alloc] initWithFrame:
                 [[UIScreen mainScreen] bounds]];

  self.window.backgroundColor = [UIColor whiteColor];
  [self.window makeKeyAndVisible];
  return YES;
}

Here is what is happening in this code:

  1. We allocated a Core Foundation string and placed it inside the coreFoundationString local variable. Since this is a Core Foundation object, ARC will not apply storage attributes to it, so we need to handle its memory manually. Its retain count is 1, as with any newly created variable.

  2. Then we typecast this Core Foundation string to a generic object of type id. Note that we didn’t retain or release this object, so the retain count on both unknownObjectType and coreFoundationString stays 1. We simply typecasted it to an object of type id.

  3. Now we are retaining the generic object of type id and placing the resulting object into another Core Foundation string. At this time, the retain count on the coreFoundationString, unknownObjectType, and anotherString variables is 2 and all three of these variables point to the same location in the memory.

  4. What we are doing after that is to assign the value inside coreFoundationString to a strong local NSString using the __bridge_transfer typecasting option. This will make sure that the coreFoundationString object will get released after this assignment (the retain count will go from 2 to 1) and it will again be retained (because of the strong NSString variable, shooting the retain count from 1 to 2 again) So now coreFoundationString, unknownObjectType, anotherString and the objCString variables all point to the same string with the retain count of 2.

  5. The next stop is setting our strong local variable objCString to nil. This will release this variable and our string’s retain count will go back to 1. All these local variables are still valid and you can read from them because the retain count of the string that all of them point to is still 1.

  6. Then we are explicitly releasing the value in the anotherString variable. This will set the release count of our object from 1 to 0 and our string object will get deallocated. At this point, you should not use any of these local variables because they are pointing to a deallocated object—except for the objCString strong local variable, whose value was set to nil by us.

See Also

Recipe 1.17

Get iOS 5 Programming Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.