4

假设一个方法CFErrorRef通过指针返回 a 。这个返回的错误可能是NULL. 那么执行静止不动是否安全,__bridge_transfer或者我应该检查NULL.

例如

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/函数/CFRelease

4

4 回答 4

3

您不需要检查 NULL。

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

在您的情况下,ARC 将为 插入一个版本error,但如果error碰巧为 nil,则它是一个简单的无操作。

于 2014-07-12T02:40:10.523 回答
2

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

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

于 2014-07-12T00:41:50.113 回答
1

The direct answer to the question is yes, you can use __bridge_transfer on NULL. But this isn't the right question.

Read the documentation on ABAddressBookCreateWithOptions. In particular, check out the documentation for error:

On error, contains error information. See “Address Book Errors.”</p>

This is important.

  1. error's value in the case of success is not documented.
  2. error being nil/NULL/0 (ever) is not documented.

This isn't academic. Some APIs have historically set error to invalid values. Imagine the call set the CFError to -1. That's "valid" since the non-NULL reply means you're not supposed to interpret the error, but bridge casting -1 to a NSError will probably crash.

That means you must not touch cfError unless an error is indicated by ABAddressBookCreateWithOptions returning NULL.

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

You didn't ask this, but one additional wrinkle here is that bridges aren't even required if the compiler recognizes that something is 0-equivalent. For instance, this code will compile silently (assuming _thing1 and _thing2 are instance variables):

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

This is sloppy code, and I you should not do this intentionally, but knowing it builds cleanly… it's a good thing to look for. I ran into a bug caused by something like this:

- (NSNumber *)someCalculationWithError:(NSError *)error {
   return 0; // meant to return @(0)
}
于 2014-07-14T18:27:48.900 回答
0

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

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

于 2014-07-12T00:08:18.310 回答