收集元素的桥梁铸件

Posted

技术标签:

【中文标题】收集元素的桥梁铸件【英文标题】:Bridge casts for collection elements 【发布时间】:2013-06-05 20:19:00 【问题描述】:

我正在使用一个供应商 API,它返回一个 CFDictionaryRef,它可以包含各种 CF 对象类型并且调用者需要 CFRelease。我想将其转换为 NSDictionary 以便更轻松地使用它,并希望确保我了解我在转换方面正确处理了元素。

在我看来,免费桥接类型(例如 CFString、CFNumber)只是由 NSDictionary 处理,我可以像一直是 Obj-C 类型一样获取 NS 类型(我是猜想有一个桥梁演员在封面下进行)。

对于非免费桥接类型(例如 CFHost),看起来我可以将结果从 -valueForKey: 桥接到 CF 类型并从那里开始,但我不肯定是否需要释放它值与否。

这里有一些说明问题的示例代码。这是正确的处理方式吗?

// Caller is responsible for releasing returned value
//
+ (CFDictionaryRef)someCFCreateFunctionFromVendor

    CFMutableDictionaryRef cfdict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    CFDictionarySetValue(cfdict, CFSTR("string1"), CFSTR("value"));
    int i = 42;
    CFDictionarySetValue(cfdict, CFSTR("int1"), CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &i));

    CFHostRef host = CFHostCreateWithName(kCFAllocatorDefault, CFSTR("myhost"));
    CFDictionarySetValue(cfdict, CFSTR("host1"), host);
    return cfdict;


+ (void)myMethod

    NSDictionary *dict = CFBridgingRelease([self someCFCreateFunctionFromVendor]);
    for (NSString *key in [dict allKeys]) 
        id value = [dict valueForKey:key];
        NSLog(@"%@ class: %@", key, [value class]);

        if ([value isKindOfClass:[NSString class]]) 
            NSString *str = (NSString *)value;
            NSLog(@"%@ is an NSString with value %@", key, str);
         else if ([value isKindOfClass:[NSNumber class]]) 
            NSNumber *num = (NSNumber *)value;
            NSLog(@"%@ is an NSNumber with value %@", key, num);
         else if ([value isKindOfClass:[NSHost class]]) 
            NSLog(@"%@ is an NSHost", key); // never hit because no toll-free bridge to NSHost
         else 
            NSLog(@"%@ is an unexpected class", key);
        

        // Sample handling of non-toll-free bridged type
        if ([key isEqualToString:@"host1"]) 
            CFHostRef host = (__bridge CFHostRef)value;
            NSArray *names = (__bridge NSArray *)(CFHostGetNames(host, false));
            NSLog(@"host1 names: %@", names);
            // I don't think I need to CFRelease(host) because ARC is still handling value
        
    

输出...

string1 class: __NSCFConstantString
string1 is an NSString with value strvalue 
int1 class: __NSCFNumber
int1 is an NSNumber with value 42
host1 class: __NSCFType
host1 is an unexpected class
host1 names: ( myhost )

【问题讨论】:

【参考方案1】:

具有讽刺意味的是,您的代码中唯一的错误是在核心基础中,非 ARC 的东西。您的+someCFCreateFunctionFromVendor 方法调用CFNumberCreate()CFHostCreateWithName(),它们都是创建函数,但在将对象添加到字典后不会CFRelease()。它应该。否则,就是泄漏。顺便说一下,静态分析器会捕捉到这一点。 (对于CFNumber,这意味着您必须将创建拆分为单独的行,以便在将对象添加到字典后引用它。)

您不能释放+myMethod 中的主机对象,因为该代码没有获得它的所有权。它与ARC无关。您也不会在 MRR(手动保留/释放)代码中发布它。

【讨论】:

很好,也是一个完美的例子,说明了为什么我想将我们正在使用的 API 部分包装在 Foundation 类中,这样团队中的其他人就不需要处理 CFTypes。谢谢。

以上是关于收集元素的桥梁铸件的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin 协程Flow 流异常处理 ( 收集元素异常处理 | 使用 try...catch 代码块捕获处理异常 | 发射元素时异常处理 | 使用 Flow#catch 函数捕获处理异常 )

Kotlin 协程Flow 流异常处理 ( 收集元素异常处理 | 使用 try...catch 代码块捕获处理异常 | 发射元素时异常处理 | 使用 Flow#catch 函数捕获处理异常 )

MPI_Gather 的问题无法将 8 个 32 个元素的数组收集到一个 256 个元素的大数组中

jQuery 问题收集

csharp 过滤元素收集器

如何有效地收集给定数组中的重复元素?