Подтвердить что ты не робот

Мост iOS vs bridge_transfer

Я запутался с bridge и bridge_transfer, это правильно?

-(void)getData{
    ABAddressBookRef addressBook = ABAddressBookCreate();
    NSArray *allPeople = (__bridge_transfer NSArray*)ABAddressBookCopyArrayOfAllPeople(addressBook);

    NSString *name;
    for ( int i = 0; i < [allPeople count]; i++ )
    {
        name = (__bridge_transfer NSString *) ABRecordCopyValue((__bridge ABRecordRef)[allPeople objectAtIndex:i], kABPersonFirstNameProperty);
    }
    CFRelease(addressBook);
    allPeople = nil;
}

Есть ли кто-нибудь, кто может объяснить мне, как их использовать?

4b9b3361

Ответ 1

Если вы включили автоматический отсчет (ARC), код верен.

В ваших утверждениях есть два __bridge_transfer. В результате право собственности на созданные CFObjects будет передано NSObjects. Если вы включили ARC, они будут автоматически освобождены. Если вы использовали __bridge вместо этих двух операторов, вам нужно явно вызвать CFRelease для выпуска CFObjects, созданных API *Copy.

Оператор __bridge также верен. Потому что вы ссылаетесь на NSObject в CF API. Вы не передаете право собственности, так что ARC освободит его.

Ответ 2

Это очень просто. Когда вы используете ARC (автоматический подсчет ссылок), компилятор позаботится о подсчете количества объектов, указываемых вашими переменными. Когда счетчик переходит в 0, объект автоматически связывается. SO для вещей, которые исходят из структуры низкого уровня, как основа ядра, компилятор не знает, что делать. Поэтому вы используете BRIDGE, если хотите просто сказать компилятору "проигнорировать это, я выпущу его, когда мне это нужно". или перенос моста, если вы хотите сказать: "Рассматривайте это как объект и отпустите его, когда ссылка идет на 0).

Когда вы это сделаете, вы создаете копию, которая при нормальных обстоятельствах должна быть выпущена с помощью "CFRelease":

ABAddressBookCopyArrayOfAllPeople(addressBook)

Однако добавив это, вы передаете право собственности на объект objective-c:

NSArray *allPeople = (__bridge_transfer NSArray*)........

Таким образом, NSArray будет управляться ARC.


Обратите внимание, что, как упоминает JRG, выполните следующее:

CFRelease(addressBook);

В любом случае не влияет на вновь созданный объект, а вместо этого на оригинал, который вы все еще должны вручную выпустить: (Легко сказать, потому что эти методы обычно имеют копию create или в своих именах)


Что-то, что не происходит в вашем коде, но вы должны быть осторожны, это то, что освобождение базовых объектов ядра, которые имеют NULL с CFRelease, вызовет ошибку. Как Павел упоминает в своем комментарии.

Ответ 3

Луис Оскар. Я все еще разрабатываю свое понимание ARC, но я считаю, что адресная книга нуждается в CFRelease. ARC не управляет адресной книгой. NSArray * allPeople управляется ARC через подсказку литирования __bridge_transfer и создается как копия оригинала. Без CFRelease адресная книга будет протекать.

Ответ 4

Одно редактирование: я считаю, что вызов CFRelease на ноль-объекте приводит к сбою приложения