__bridge_transfer对NULL对象是否有效

时间:2014-07-12 00:05:31

标签: ios objective-c core-foundation toll-free-bridging

假设一个方法通过指针返回CFErrorRef。返回的错误可能是NULL。因此,执行__bridge_transfer仍然是安全的,或者我应该检查NULL

E.g。

CFErrorRef cfError;
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, &cfError);

NSError *error = (__bridge_transfer NSError *)cfError;

我在文档中没有看到任何提及此问题,CFRelease文档明确指出This value must not be NULL. https://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFTypeRef/Reference/reference.html#//apple_ref/c/func/CFRelease

4 个答案:

答案 0 :(得分:3)

您无需检查NULL。

ARC是一种严格的编译时机制。使用__bridge_transfer时,您只是将变量的内存管理职责转移给编译器。 cfError在运行时是否恰好为NULL与编译器完全无关。

在您的情况下,ARC会为error插入一个版本,但如果error恰好是零,那么这是一个简单的无操作。

答案 1 :(得分:2)

如果函数的返回值为NULL,则错误将为非NULL。 这种CF函数的模式是将错误检查包装在if语句中。 if (addressBookRef == NULL) { /* your error handling here */}

除非非NULL,否则不应尝试桥接任何内容。对象所有权或更准确地保留计数和减少它的责任,对于NULL或nil没有意义。这将是一种反模式。 充其量只是一个空操作。 使用Objective-C将消息发送到nil很好,包括保留和释放。 将NULL值传递给CFRelease()或CGRetain()

是不合适的

答案 2 :(得分:1)

问题的直接答案是肯定的,您可以__bridge_transfer使用NULL。但这不是正确的问题。

阅读ABAddressBookCreateWithOptions上的文档。特别是,请查看error的{​​{1}}:

  

出错时,包含错误信息。请参阅“地址簿错误。”

这很重要。

  1. error未成功记录成功案例的价值。
  2. error nil / NULL / 0永远)未记录在案。
  3. 这不是学术性的。某些API历来将错误设置为无效值。想象一下,调用将CFError设置为-1。那"有效"因为非NULL回复意味着您不应该解释错误,但是将-1桥接到NSError可能会崩溃。

    这意味着您不得触摸 cfError,除非ABAddressBookCreateWithOptions指示错误返回NULL。

    CFErrorRef cfError;
    NSError *error;
    ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, &cfError); 
    if (addressBookRef == NULL) {
        error = (__bridge_transfer NSError *)cfError;
    }
    

    你没有问过这个问题,但是另外一个问题是,如果编译器认识到某些东西是0等效的话,那么甚至不需要桥接。例如,此代码将以静默方式编译(假设_thing1_thing2是实例变量):

    - (id)bar {
        if (_thing1) return NO;
        if (_thing2) return 0;
        return NULL;
    }
    

    这是邋code的代码,我应该有意识地这样做,但要知道它干净利落地构建......这是一件好事。我遇到了这样的错误:

    - (NSNumber *)someCalculationWithError:(NSError *)error {
       return 0; // meant to return @(0)
    }
    

答案 3 :(得分:0)

与NSObject不同,向NULL CF对象发送消息是不行的。我不知道具体的桥接转换,但我猜不,使用__bridge_transfer将CF对象转换为NSObject是不行的。

为什么不试试看?将其转换为实例方法的本地范围中的变量。这样,一旦方法超出范围,系统就应该尝试释放对象。