【问题标题】:What is CFArray and difference between CFArray vs NSArray什么是 CFArray 以及 CFArray 与 NSArray 之间的区别
【发布时间】:2016-04-22 05:40:05
【问题描述】:

这可能是一个重复的问题,但我浏览了这么多博客和文档,但我仍然无法弄清楚 CFArray 是什么。

就性能而言,哪个最好,何时使用以及在哪种情况下使用。 请在这个话题上有所启发。

【问题讨论】:

    标签: objective-c nsarray cfarraybsearchvalues


    【解决方案1】:

    CFArrayNSArray,反之亦然。

    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* 类型实际上只是 NS* 类的包装器......所以,当您调用 CFCreate*() 时,您实际上是在返回一个 NS* 对象引用作为返回值。
    • 这个答案不是 100% 准确的。见stackoverflow.com/a/56802428/983912
    • @LeoNatan – 是的,如果我理解正确,您指的是答案中toll-free bridged 链接中的注释中涵盖的内容,并且可以适用于其他CF“免费”类型也是。
    • 对。我不知道这个注释。我至少见过一种情况,在 AppKit 中返回了一个 uint32_t 数组,如果桥接它会崩溃。
    【解决方案2】:
    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 循环旁边被注释掉了。

    【讨论】:

      【解决方案3】:

      重要的是要注意,虽然其他答案在常见情况下是正确的,但可以创建与 Objective C 完全不兼容的CFArray 变体。创建CFArray 时,会提供callback functions .如果提供标准kCFTypeArrayCallBacks,则该数组确实兼容并且免费桥接到Objective C。但是,可以提供自定义回调函数,例如,将值类型包含为数组值(而@987654326 @ 要求所有值都是CFType/objc_object)。

      了解这种差异很重要,因为在极少数情况下,Apple 框架返回 CFArray 对象,这些对象不得桥接到 NSArray,尤其是在使用 ARC 时。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-08-11
        • 1970-01-01
        • 2014-07-10
        • 1970-01-01
        • 1970-01-01
        • 2011-10-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多