我试图理解为什么存在CF和NS对象,它们似乎做同样的事情并且可以通过免费桥接互换。如果CFArray和NSArray做同样的事情,并且我可以自由地在它们之间施放,那么它们存在的重点是什么?是否有关于何时使用其中一个的经验法则? CF对象只是旧框架中的遗留对象吗?任何有关这方面的见解将不胜感激。
答案 0 :(得分:63)
按顺序回答您的问题:
他们两个存在的意义何在?有几个原因。
如果你想提供一个C API,比如Carbon API,你需要引用计数对象的数组和字典之类的东西,你需要像Core Foundation(提供CFArray
)这样的库,以及当然它需要一个C API。
如果要为在Windows上使用的第三方编写库(例如),则需要提供C API。
如果您想编写一个低级库,比如说要与操作系统的内核连接,并且您不想要Objective-C消息传递的开销,那么您需要一个C API。< / p>
因此,这些是拥有Core Foundation(一个纯C库)的充分理由。
但是如果你想在Objective-C中提供更高级别,更令人愉快的API,你需要Objective-C对象来表示数组,字典,引用计数对象等等。所以你需要Foundation,这是一个Objective-C库。
什么时候应该使用其中一种?通常,您应该尽可能使用Objective-C类(例如NSArray
),因为Objective-C界面使用起来更加愉快:myArray.count
(或[myArray count]
)更容易读写比CFArrayGetCount(myArray)
。只有在您真正需要时才应使用Core Foundation API:当您处于没有Objective-C的平台上时,或者您需要Core Foundation API提供但Objective-C的功能时对象缺乏。例如,您可以在创建CFArray
或CFDictionary
时指定回调,以便存储非引用计数对象。 NSArray
和NSDictionary
类不允许您这样做 - 他们总是假设您正在存储引用计数的对象。
CF对象只是遗留对象吗?一点也不。事实上,Nextstep已经存在多年,只有Objective-C Foundation库和没有(公共)Core Foundation库。当Apple需要在相同的低级操作系统设施之上同时支持Carbon API和Cocoa API时,他们创建(或公开)Core Foundation以支持两者。
顺便说一句,Core Foundation的某些内容是开源的。您可以在此处找到适用于Mac OS X 10.10.5的开源部分:https://opensource.apple.com/source/CF/CF-1153.18/。我发现CFRunLoop
和CFStream
的源代码非常有用。
答案 1 :(得分:11)
Core Foundation是各种常见数据结构的C API。大多数这些数据结构在Cocoa中具有等价物,但不是全部。大多数相同的是免费桥接,允许它们互换使用,但不是全部。
免费桥接是一个非常聪明的实施技巧。如果您想了解基础细节,请参阅@Matt Wilding指出的ridiculous_fish post。它是关于这一主题的最权威的(并且对iOS:PTL第19章的主要影响也解释了它是如何工作的)。但对大多数目的而言,这并不重要。正如马特所说,你通常可以假装NSArray
与CFArrayRef
相同。在许多情况下这并不是真的,但它有时是正确的,而且大部分时间都足够接近。这与说@"stuff"
与包含NSString
的{{1}}相同是一样的。这大部分都是正确的,但并不完全正确。
当OS 9移动到OS X时,提供对类似Objective-C的数据结构的C访问非常方便。今天,许多低级框架都出于性能原因而公开了C API。你不应该把CF视为“遗产”或“内部”。您应该将其视为低级别,并且只应在需要它提供的功能时使用它,或者正在处理需要它的低级框架。
CF对象通常比NS对象更灵活。例如,stuff
可以包含非对象键和值,而CFDictionaryRef
则不能。 (当然他们是免费的桥接,所以你可以创建一个非保留NSDictionary
,然后将其视为CFDictionaryRef
。棘手......)
当Apple发布新框架时,您会注意到他们经常首先公开C API,然后再添加Objective-C API。这就是学习Core Foundation的好主意,即使你每天都不使用它。但是如果可能的话,你通常应该使用ObjC。
答案 2 :(得分:3)
这个问题有一些历史。核心基金会是该运营的大脑。它主要是用C语言编写的。它是在Apple收购NEXT及其API时创建的,并且对它们有很大帮助。 NS *类通常只是构建在CF *类型之上的Objective C抽象接口。所以,当你问为什么CFArray和NSArray都存在时,答案就是他们实际上并没有。 NSArrays 是 CFArrays,NSStrings 是 CFStrings等。这就是为什么可以进行免费桥接的原因。
有关更有趣和详细的阅读,我会推荐您this blog post。
答案 3 :(得分:1)
CF代表CoreFoundation。名称中带有CF的暴露对象只是常规的Core Foundation对象,用C语言编写。所有对象都与他们的Cocoa Touch Foundation朋友在Objective-C土地上免费桥接。它们通常是不透明的指针。
NS代表NextStep,它是Mac OS X构建的旧操作系统。 NS前缀对象通常完全用Objective-C或C或甚至一些C ++编写。
这实际上取决于每个对象需要做什么。对于我来说,使用NSString在纯Objective-C中工作当然更容易,然后我可以使用CFString混合使用C和Objective-C,但是CF对象可以做一些事情,NS对象可以做到' t(主要是非常低级别的东西)。与NS同行相比,CF对象在参考,突变和检查方面也涉及更多。
(为了将来参考,还有一些前缀:CoreGraphics的CG,UIKit的UI,QuickLook的QL,AVFoundation的AV,MediaPlayer的MP,MessageFoundation的MF,GLKit的GL和MapKit的MK)(如果我错过了,我很乐意编辑。)