天天看点

ARC Basics 2:Objective-C Toll Free Bridging and ARC Bridged Casts

Objective-C Toll Free Bridging

Interoperability is provided for a number of data types in the C-based Core Foundation Frameworkand the Objective-C-based Foundation Framework. This capability, referred to as toll-free bridging, allows you to use the same data type as the parameter to a Core Foundation function call or as the receiver of an Objective-C message. You can cast one type to the other to suppress compiler warnings. Some of the more commonly used toll-free bridged data types are listed in Table 6-1; it includes the Core Foundation type and the corresponding Foundation Framework type.

Table 6-1. Toll-Free Bridging Data Types

Core Foundation Type Foundation Type
CFArrayRef NSArray
CFDataRef NSData
CFDateRef NSDate
CFDictionaryRef NSDictionary
CFMutableArrayRef NSMutableArray
CFMutableDataRef NSMutableData
CFMutableDictionaryRef NSMutableDictionary
CFMutableSetRef NSMutableSet
CFMutableStringRef NSMutableString
CFNumberRef NSNumber
CFReadStreamRef NSInputStream
CFSetRef NSSet
CFStringRef NSString
CFWriteStreamRef NSOutputStream

With toll-free bridging, the compiler implicitly casts between Core Foundation and Foundation types. For example, a variable of type CFStringRef is used as an argument to an Objective-C method inListing 6-9.

Listing 6-9.  Toll-Free Bridging Implicit Cast

CFStringRef cstr = CFStringCreateWithCString(NULL, "Hello, World!",
                                                 kCFStringEncodingASCII);
NSArray *data = [NSArray arrayWithObject:cstr];      

The [NSArray arrayWithObject:] class method takes a parameter of type id (in other words, an Objective-C object pointer) as an argument, but is passed as CFStringRef. Because CFStringRef is a toll-free bridged data type, the cstr parameter is implicitly cast to an NSString object (see Table 6-1). To remove the compiler warning for the implicit cast, the parameter is cast, as shown in Listing 6-10.

Listing 6-10.  Toll-Free Bridging Explicit Cast

CFStringRef cstr = CFStringCreateWithCString(NULL, "Hello, World!",
                                                 kCFStringEncodingASCII);
NSArray *data = [NSArray arrayWithObject:(NSString *)cstr];      

As mentioned in the previous section, the Objective-C compiler does not automatically manage the lifetimes of Core Foundation data types. Therefore, to use Core Foundation toll-free bridged types in ARC memory managed Objective-C programs, it is necessary to indicate the ownership semantics involved with these types. In fact, the code in Listing 6-10, as is, will not compile when using ARC!For Objective-C programs that use ARC memory management, you must indicate whether the life cycle of a toll-free bridged type is to be managed by ARC or managed programmatically. You do this by using ARC bridged casts.

ARC Bridged Casts

ARC bridged casts enable the use of toll-free bridged types when using ARC. These casting operations are prefaced with the special annotations __bridge , __bridge_retained , and __ bridge_transfer.

  • The __bridge annotation casts an object from a Core Foundation data type to aFoundation object (or vice-versa) without transfer of ownership. In other words, if you dynamically create a Foundation Framework object, and then cast it to a Core Foundation type (via toll-free bridging), the __bridge annotation informs the compiler that the object’s life cycle is still managed by ARC. Conversely, if you create a Core Foundation data type and then cast it to a Foundation Framework object, the__bridge annotation informs the compiler that the object’s life cycle must still be managed programmatically (and is not managed by ARC). Note that this annotation removes the compiler error but doesn’t transfer ownership; thus, care is required when using it to avoid memory leaks or dangling pointers.
  • The __bridge_retained annotation is used to cast a Foundation Framework object to a Core Foundation data type and transfer ownership from the ARC system. You are then responsible for programmatically managing the lifetime of the bridged data type.
  • The __bridge_transfer annotation is used to cast a Core Foundation data type to aFoundation object and also transfer ownership of the object to the ARC system. ARC will then programmatically manage the lifetime of the bridged object.

The syntax for using a bridged cast annotation in a cast operation is

(annotation castType)variableName      

This differs from a regular cast operation in that the annotation is prepended to the cast type. The ARC bridged casts can be used not only for toll-free bridged types, but also anywhere your Objective-C code needs to use access memory not managed as Objective-C objects. Listing 6-11 updates the previous example with an ARC bridged cast.

Listing 6-11.  Toll-Free Bridging with an ARC Bridged Cast

CFStringRef cstr = CFStringCreateWithCString(NULL, "Hello, World!",
                                                 kCFStringEncodingASCII);
NSArray *data = [NSArray arrayWithObject:(__bridge_transfer NSString *)cstr];      

Notice that the annotation precedes the type being cast to. This annotation transfers ownership of the bridged object to ARC, which will now manage the object’s life cycle. OK, enough theory, now let’s create some examples that demonstrate the use of ARC bridged casts!