Darshan
Darshan

Reputation: 2379

What is CFArray and difference between CFArray vs NSArray

This might be a duplicate question but I have gone through so many blogs and documents but still can't figure out what CFArray is.

What is the difference between CFArray and NSArray? In terms of performance, when should I use one over the other?

Upvotes: 5

Views: 4419

Answers (3)

Léo Natan
Léo Natan

Reputation: 57060

It's important to note, that while the other answers are correct in the common case, it is possible to create CFArray variants that are completely incompatible with Objective C. When a CFArray is created, callback functions are provided. If the standard kCFTypeArrayCallBacks is provided, the array is indeed compatible and toll-free bridged to Objective C. However, it is possible to provide custom callback functions, and, for example, include value types as the array values (whereas NSArray requires that all values are CFType/objc_object).

It is important to know this difference, as in some rare cases, the Apple frameworks return CFArray objects which must not be bridged to NSArray, especially when using ARC.

Upvotes: 2

CRD
CRD

Reputation: 53010

A CFArray is an NSArray and vice-versa.

Core Foundation (where the CF comes from in the name) is Apple's C-oriented collection of functions and data types. Cocoa (the NS comes from NextStep, Cocoa's ancestor) is Apple's Objective-C framework.

Certain types in the two two frameworks are toll-free bridged - that means the data structure is shared between the two frameworks, Core Foundation operates on it using C-style function calls, Cocoa operates on it using Objective-C style method calls.

Sometimes one framework might provide operations the other does not, but in general you use Cocoa from Objective-C and Core Foundation from C when considering a toll-free bridge type.

Cocoa objects are automatically managed by ARC, a big advantage. In Core Foundation you use manual memory management. Objective-C has a number of "bridge" casts which inform the compiler when you are transferring responsibility for memory management between ARC and manual Core Foundation calls.

Given they are the same data-structure any performance difference is down to the such things as an extra call-level overhead if a Cocoa method just calls a Core Foundation one, etc. In general you should not be concerned about this unless you've identified a performance issue.

HTH

Upvotes: 9

Abhinandan Pratap
Abhinandan Pratap

Reputation: 2148

CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, arraySize, &kCFTypeArrayCallBacks);
for (int i=0;i<arraySize;i++) {
    CFStringRef string = CFBridgingRetain(@"This is an awesome string"); // CFStringCreateWithCString(kCFAllocatorDefault, "This is an awesome string", kCFStringEncodingUTF8);
    CFArrayAppendValue(array, string);
    CFRelease(string);
}

CFIndex count = CFArrayGetCount(array);
for (int i=0;i<count;i++) {
    CFStringRef string = CFArrayGetValueAtIndex(array, i);
}
CFRelease(array);

let’s go over the CFArray code. In the CoreFoundation version, we first create a mutable CFArray (CFMutableArray) via the CFArrayCreateMutable() function call, providing the allocator, array size and the callback function. We then setup a very conventional-looking for loop, iterating over the array the number of time indicated by arraySize (this number will change in our tests). A string is then created and appended to the array and released. You might notice that we actually create and Objective-C string literal and transfer the ownership over to CoreFoundation via CFBridgingRetain(). This means that ARC will no longer take care of releasing the string for us and we must do so explicitly with CFRelease(). An alternative to this is to use create a string with a CoreFoundation call to CFStringCreateWithCString() (which is commented out), but this method is much slower and we are interested in comparing the array performance, not string allocation performance. The second portion of the code will get the array count, setup another loop and get the value at index with every iteration. We don’t actually do anything with the string.

NSMutableArray *container = [[NSMutableArray alloc] initWithCapacity:arraySize];
for (int i=0;i<arraySize;i++) {
    NSString *string = @"This is an awesome string";
    [container addObject:string];
}

NSUInteger count = [container count];
for (int i=0;i<count;i++) { // (NSString *string in container) {
    NSString *string = container[i];
}

The Objective-C Foundation counterpart is very similar in nature but removes the need for CFRelease() as we are under ARC. Most of this code is pretty self-explanatory so we won’t go through it in detail. One thing to point out, however, is that with Foundation you have the option of using Fast Enumeration, which will actually give you some performance gains, as we’ll see later on. This is commented out beside the conventional for loop.

Upvotes: 5

Related Questions