Мост iOS против bridge_transfer - PullRequest
       9

Мост iOS против bridge_transfer

33 голосов
/ 25 марта 2012

Я запутался с 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;
}

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

Ответы [ 4 ]

42 голосов
/ 25 марта 2012

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

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

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

19 голосов
/ 25 марта 2012

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

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

ABAddressBookCopyArrayOfAllPeople(addressBook)

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

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

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


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

CFRelease(addressBook);

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


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

1 голос
/ 09 июля 2012

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

0 голосов
/ 13 апреля 2012

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

...