【发布时间】:2016-04-22 05:40:05
【问题描述】:
这可能是一个重复的问题,但我浏览了这么多博客和文档,但我仍然无法弄清楚 CFArray 是什么。
就性能而言,哪个最好,何时使用以及在哪种情况下使用。 请在这个话题上有所启发。
【问题讨论】:
标签: objective-c nsarray cfarraybsearchvalues
这可能是一个重复的问题,但我浏览了这么多博客和文档,但我仍然无法弄清楚 CFArray 是什么。
就性能而言,哪个最好,何时使用以及在哪种情况下使用。 请在这个话题上有所启发。
【问题讨论】:
标签: objective-c nsarray cfarraybsearchvalues
Core Foundation(名称中的CF 来源于此)是Apple 面向C 的函数和数据类型的集合。 Cocoa(NS 来自 NextStep,Cocoa 的祖先)是 Apple 的 Objective-C 框架。
两个框架中的某些类型是toll-free bridged - 这意味着数据结构在两个框架之间共享,Core Foundation 使用 C 风格的函数调用对其进行操作,Cocoa 使用 Objective-C 风格的方法调用对其进行操作.
有时一个框架可能提供另一个框架不提供的操作,但一般来说,在考虑免费桥接类型时,您会使用 Objective-C 的 Cocoa 和 C 的 Core Foundation。
Cocoa 对象由 ARC 自动管理,这是一个很大的优势。在 Core Foundation 中,您使用手动内存管理。 Objective-C 有许多"bridge" casts,当您在 ARC 和手动 Core Foundation 调用之间转移内存管理责任时,它们会通知编译器。
鉴于它们是相同的数据结构,任何性能差异都归结为诸如如果 Cocoa 方法仅调用核心基础方法等额外的调用级开销等。通常你不应该担心这一点,除非您发现了性能问题。
HTH
【讨论】:
CF“免费”类型也是。
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);
让我们回顾一下 CFArray 代码。在CoreFoundation版本中,我们首先通过CFArrayCreateMutable()函数调用创建一个可变CFArray(CFMutableArray),提供分配器、数组大小和回调函数。然后,我们设置了一个非常传统的 for 循环,以 arraySize 指示的时间数对数组进行迭代(这个数字将在我们的测试中改变)。然后创建一个字符串并将其附加到数组并释放。您可能会注意到,我们实际上创建了 Objective-C 字符串文字并通过 CFBridgingRetain() 将所有权转移给 CoreFoundation。这意味着 ARC 将不再为我们释放字符串,我们必须使用 CFRelease() 明确地这样做。另一种方法是使用 CoreFoundation 调用 CFStringCreateWithCString() 创建一个字符串(已注释掉),但这种方法要慢得多,我们感兴趣的是比较数组性能,而不是字符串分配性能。代码的第二部分将获取数组计数,设置另一个循环并在每次迭代时获取索引处的值。我们实际上并没有对字符串做任何事情。
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];
}
Objective-C Foundation 的对应物在本质上非常相似,但由于我们在 ARC 下,因此不需要 CFRelease()。大部分代码都是不言自明的,所以我们不会详细介绍。然而,需要指出的一件事是,使用 Foundation,您可以选择使用快速枚举,这实际上会给您带来一些性能提升,我们稍后会看到。这在传统的 for 循环旁边被注释掉了。
【讨论】:
重要的是要注意,虽然其他答案在常见情况下是正确的,但可以创建与 Objective C 完全不兼容的CFArray 变体。创建CFArray 时,会提供callback functions .如果提供标准kCFTypeArrayCallBacks,则该数组确实兼容并且免费桥接到Objective C。但是,可以提供自定义回调函数,例如,将值类型包含为数组值(而@987654326 @ 要求所有值都是CFType/objc_object)。
了解这种差异很重要,因为在极少数情况下,Apple 框架返回 CFArray 对象,这些对象不得桥接到 NSArray,尤其是在使用 ARC 时。
【讨论】: