Derek Thurn
Derek Thurn

Reputation: 15365

If you bridge a CFArrayRef of CFStringRefs to NSArray, can you treat the contents as NSStrings?

Suppose I have a CFArrayRef containing CFStringRefs inside it and I bridge it over to NSArray using CFBridgingRelease(). Can I now treat the contents of the array as regular NSString instances and call all of the usual NSString methods?

If so, does this mean toll-free bridging happens recursively throughout the object when it's bridged? E.g. if I had a CFArray of CFArrays of CFDictionaries or something, they'd all be transparently converted to NSArray, NSDictionary, etc?

Upvotes: 4

Views: 970

Answers (3)

jtbandes
jtbandes

Reputation: 118691

Let me try and take a simpler approach to an answer:

  • A CFArrayRef can be treated as an NSArray* and vice versa.

  • A CFStringRef can be treated as an NSString* and vice versa.

  • Thus, an CFArray of CFStrings is an NSArray of NSStrings. You just need to cast it. (In so doing with __bridge_*, you also transfer the memory management to ARC.)

Upvotes: 0

Ken Thomases
Ken Thomases

Reputation: 90571

CRD's answer is good and I've given it a +1. Here's a bit more explanation:

First, type-casting is a purely compile-time thing. And it doesn't cost anything. It just tells the compiler not to complain.

Toll-free casting of Core Foundation types to Cocoa types is because those objects are, under the hood, the same thing. The cast is just necessary to inform the compiler of that fact. Such a cast doesn't "do" anything. For example, in non-ARC code:

CFStringRef cfstring = /* ... */;
NSString* nsstring = (NSString*)cfstring;

That assignment is still just an assignment. The pointer value from cfstring is still just copied verbatim into the storage of nsstring. Nothing else happens.

Depending on how you obtained the CFString that cfstring was pointing to, you may have had a responsibility to release it. Since this is non-ARC, you still have that responsibility after it has been assigned to nsstring, which you can discharge either by calling CFRelease(cfstring) or [nsstring release] or [nsstring autorelease] when you're done with it. Once you do that, the value in both variables must be considered unusable as dangling pointers.

The case with ARC is only slightly different. An ARC bridging cast is also a compile-time thing, but it affects what code the compiler emits for automatic memory management. Since it has emitted different code, that technically has implications for run-time, but they are not related to the type-cast as such. The bridging cast tells the compiler whether it should emit retains or releases (or neither) of the object which is the subject of the expression. That's all; just a question of retaining or releasing the object. So, it has no effect on, say, objects within an array because those objects are not the subject of the expression, the array is. And it doesn't even do anything to the array beyond potentially retaining or releasing it.

Upvotes: 2

CRD
CRD

Reputation: 53000

Toll free bridging does not involve any conversion (or there would be a cost), so talking about doing it recursively does not make sense.

What toll free bridging does in your case is determine who is responsible for managing the lifetime of the object - the programmer for the CF array, ARC for the NS array.

Further whether an object internally uses manual memory management or ARC is not important to the user of that object - they can use either style.

Combine the above and you have your answer: once you've handed your CF array of strings over to ARC your job is done.

HTH

Upvotes: 4

Related Questions