Eric
Eric

Reputation: 1678

CF objects vs NS objects

I'm trying to understand why there exists both CF and NS objects, which seem to do the same thing and are interchangeable through toll-free bridging. If, say, CFArray and NSArray do the same thing, and I can cast between them freely, what's the point in both of them existing? Are there rules of thumb about when to use one over the other? Are the CF objects just legacy objects from old frameworks? Any insight into this would be greatly appreciated.

Upvotes: 49

Views: 11742

Answers (4)

rob mayoff
rob mayoff

Reputation: 385670

To answer your questions in order:

  1. What's the point of them both existing? There are a few reasons.

    If you want to provide a C API, like the Carbon API, and you need things like arrays and dictionaries of referenced-counted objects, you want a library like Core Foundation (which provides CFArray), and of course it needs to have a C API.

    If you want to write libraries for third-parties to use on Windows (for example), you need to provide a C API.

    If you want to write a low-level library, say for interfacing with your operating system's kernel, and you don't want the overhead of Objective-C messaging, you need a C API.

    So those are good reasons for having Core Foundation, a pure C library.

    But if you want to provide a higher-level, more pleasant API in Objective-C, you want Objective-C objects that represent arrays, dictionaries, reference-counted objects, and so on. So you need Foundation, which is an Objective-C library.

  2. When should you use one or the other? Generally, you should use the Objective-C classes (e.g. NSArray) whenever you can, because the Objective-C interface is more pleasant to use: myArray.count (or [myArray count]) is easier to read and write than CFArrayGetCount(myArray). You should use the Core Foundation API only when you really need to: when you're on a platform that doesn't have Objective-C, or when you need features that the Core Foundation API provides but the Objective-C objects lack. For example, you can specify callbacks when creating a CFArray or a CFDictionary that let you store non-reference-counted objects. The NSArray and NSDictionary classes don't let you do that - they always assume you are storing reference-counted objects.

  3. Are the CF objects just legacy objects? Not at all. In fact, Nextstep existed for years with just the Objective-C Foundation library and no (public) Core Foundation library. When Apple needed to support both the Carbon API and the Cocoa API on top of the same lower-level operating system facilities, they created (or made public) Core Foundation to support both.

Incidentally, some of Core Foundation is open source. You can find the open source part of it for Mac OS X 10.10.5 here: https://opensource.apple.com/source/CF/CF-1153.18/. I have found the source code of CFRunLoop and CFStream to be very informative.

Upvotes: 70

Matt Wilding
Matt Wilding

Reputation: 20153

There's some history to this question. Core Foundation is the brains of the operation. It's written mostly in C. It was created with Apple's acquisition of NEXT and their APIs and owes a lot to them. The NS* classes are often just Objective C abstract interfaces built on top of the CF* types. So, when you ask why both CFArray and NSArray exist, the answer is that they actually don't. NSArrays are CFArrays, NSStrings are CFStrings, etc. That's why toll-free-bridging is possible.

For more interesting and detailed reading, I would refer you to this blog post.

Upvotes: 3

Rob Napier
Rob Napier

Reputation: 299345

Core Foundation is a C API to a variety of common data structures. Most of these data structures have equivalents in Cocoa, but not all of them. Most of the ones that are equivalent are toll free bridged, allowing them to be used interchangeably, but not all of them either.

Toll free bridging is a very clever implementation trick. If you want the underlying details, see the ridiculous_fish post that @Matt Wilding points out. It's the most authoritative on the subject (and a major influence on iOS:PTL chapter 19 which also explains how it all works). But it doesn't really matter for most purposes. As Matt notes, you can generally pretend that an NSArray is the same as a CFArrayRef. This isn't really true in many cases, but it's sometimes true, and close enough most of the time. It's the same as saying that @"stuff" is the same as an NSString containing stuff. It's mostly true, but not exactly.

When OS 9 moved to OS X, it was very convenient to provide C access to Objective-C-like data structures. Many low-level frameworks today expose C APIs for performance reasons. You shouldn't think of CF as "legacy" or "internal." You should think of it as low-level and you should only use it when you need the power it provides, or are dealing with a low-level framework that requires it.

CF objects are often more flexible than their NS counterparts. For example, CFDictionaryRef can contain non-object keys and values, while NSDictionary can't. (Of course they're toll-free bridged, so you can create a non-retaining CFDictionaryRef and then treat it as an NSDictionary. Tricky that....)

As Apple releases new frameworks, you'll notice that they often expose C APIs first, and then later add Objective-C APIs. This is a reason that it's a good idea to learn Core Foundation, even if you don't use it every day. But when possible, you generally should be using ObjC.

Upvotes: 11

CodaFi
CodaFi

Reputation: 43330

CF stands for CoreFoundation. Exposed objects with CF in their names are just regular Core Foundation objects, written in C. All objects are toll free bridged with their Cocoa Touch Foundation friends over in Objective-C land. They are usually opaque pointers.

NS stands for NextStep, which was the old OS that Mac OS X was built upon. NS-prefixed objects are usually written entirely in Objective-C or C or even some C++.

It really depends on what you need each object to do. It's certainly easier for me to work in pure Objective-C with NSString, then it is for me to work in a mix of C and Objective-C with CFString, but there are some things that CF objects can do that NS objects simply can't (mostly very low level stuff). CF objects also dabble a lot more in Ref's, mutations, and inspections than their NS counterparts.

(For future reference, there exist a few more prefixes: CG for CoreGraphics, UI for UIKit, QL for QuickLook, AV for AVFoundation, MP for MediaPlayer, MF for MessageFoundation, GL for GLKit, and MK for MapKit)(If I've missed any, I'll gladly edit).

Upvotes: 1

Related Questions