Допустим ли __bridge_transfer для объекта NULL
Допустим, метод возвращает CFErrorRef
через указатель. Эта возвращенная ошибка может быть 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
4 ответа
Прямой ответ на вопрос: да, вы можете использовать __bridge_transfer
на NULL
, Но это не правильный вопрос.
Прочитайте документацию на ABAddressBookCreateWithOptions
, В частности, ознакомьтесь с документацией для error
:
Об ошибке, содержит информацию об ошибке. См. "Ошибки адресной книги".
Это важно.
error
Значение в случае успеха не задокументировано.error
являющийсяnil
/NULL
/0
(никогда) не задокументировано.
Это не академично. Некоторые 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;
}
Это неаккуратный код, и я не должен делать это преднамеренно, но зная, что он создается чисто... это хорошая вещь, чтобы искать. Я столкнулся с ошибкой, вызванной чем-то вроде этого:
- (NSNumber *)someCalculationWithError:(NSError *)error {
return 0; // meant to return @(0)
}
Вам не нужно проверять на NULL.
ARC - строго механизм компиляции. Когда вы используете __bridge_transfer
вы просто переносите ответственность за управление памятью переменной на компилятор. Будь то cfError
бывает NULL или нет во время выполнения полностью не имеет значения для компилятора.
В вашем случае ARC вставит релиз для error
, но если error
бывает ноль, это просто не-оп
Ошибка будет отлична от NULL, если возвращаемое значение функции равно NULL. Шаблон для этого типа функции CF заключается в том, чтобы обернуть проверку ошибок в оператор if. if (addressBookRef == NULL) { /* your error handling here */}
Вы не должны пытаться соединить что-либо, если оно не NULL. Владение объектом или, точнее, сохранение количества и ответственности за его уменьшение, не имеют значения с NULL или с нулем. Это было бы анти-паттерном. В лучшем случае это нулевая операция. Отправка сообщений на ноль с помощью Objective-C - это нормально, включая сохранение и освобождение. Неверно передавать значение NULL в CFRelease() или CGRetain().
В отличие от NSObjects, отправка сообщений объектам NULL CF не подходит. Я не знаю, что конкретно происходит при связывании, но я бы предположил, что нет, приведение объекта CF к объекту NSObject с использованием __bridge_transfer НЕ подходит.
Почему бы не попробовать и посмотреть? Приведите его к переменной в локальной области видимости метода экземпляра. Таким образом, как только метод выходит из области видимости, система должна попытаться освободить объект.