ARC и мостовой состав - PullRequest
       35

ARC и мостовой состав

162 голосов
/ 12 августа 2011

С ARC я больше не могу разыгрывать CGColorRef на id. Я узнал, что мне нужно сделать актерский состав. В соответствии Clang Docs :

A бросок с мостом - приведение в стиле C, снабженное одним из трех ключевых слов:

(__bridge T) op приводит операнд к типу назначения T. Если T является указателем типа сохраняемого объекта, тогда op должен иметь невозвратный тип указателя. Если T является типом указателя без возможности сохранения, тогда у op должен быть сохраняемый тип указателя объекта. В противном случае актерский состав плохо сформирован. Передачи прав собственности нет, а ARC вставок нет сохранить операции.

(__bridge_retained T) op приводит операнд, который должен иметь сохраняемый тип указателя объекта на тип назначения, который должен быть тип безвозвратного указателя. ARC сохраняет значение при условии обычные оптимизации локальных значений, и получатель несет ответственность для балансировки + 1.

(__bridge_transfer T) op бросает операнд, который должен иметь тип указателя без возможности сохранения, к типу назначения, который должен быть тип указателя сохраняемого объекта. ARC выпустит значение в конце полного выражения, с обычной оптимизацией на локальные значения.

Эти приведения необходимы для передачи объектов в и из Контроль ARC; см. обоснование в разделе о преобразовании указатели сохраняемых объектов.

Использование __bridge_retained или __bridge_transfer наложения, чтобы убедить ARC испускает несбалансированное удержание или освобождение, соответственно, оставляет желать лучшего форма.

В каких ситуациях я бы использовал каждую из них?

Например, CAGradientLayer имеет свойство colors, которое принимает массив CGColorRef s. Я предполагаю, что я должен использовать __brige здесь, но точно почему я должен (или не должен) неясно.

Ответы [ 3 ]

213 голосов
/ 31 августа 2011

Я согласен, что описание сбивает с толку.Так как я только что понял их, я попытаюсь подвести итог:

  • (__bridge_transfer <NSType>) op или, альтернативно, CFBridgingRelease(op) используется, чтобы потреблять удерживающий счет CFTypeRef при передаче его черезв ARC.Это также может быть представлено как id someObj = (__bridge <NSType>) op; CFRelease(op);

  • (__bridge_retained <CFType>) op или, альтернативно, CFBridgingRetain(op) используется для передачи NSObject на CF-землю, давая ему +1 счет удержания.,Вы должны обработать CFTypeRef, который вы создаете таким же образом, как и результат CFStringCreateCopy().Это также может быть представлено CFRetain((__bridge CFType)op); CFTypeRef someTypeRef = (__bridge CFType)op;

  • __bridge просто приведением между указателем-землей и объектом-землей Objective-C.Если у вас нет желания использовать приведенные выше преобразования, используйте это.

Может быть, это полезно.Сам я предпочитаю макросы CFBridging… чуть-чуть перед простыми приведениями.

53 голосов
/ 29 октября 2013

Я нашел другое объяснение в документации iOS, которое, по-моему, легче понять:

  • __bridge передает указатель между Objective-C и Core Foundation без передачи права собственности.

  • __bridge_retained (CFBridgingRetain) создает указатель Objective-C на указатель Core Foundation , а также передает вам право собственности.

    Вы несете ответственность за вызов CFRelease или связанной функции для отказа от владения объектом.

  • __bridge_transfer (CFBridgingRelease) перемещает не-Objective-C указатель в Objective-C , а также передает владение ARC.

    ARC несет ответственность за отказ от владения объектом.

Источник: Бесплатные типы мостов

32 голосов
/ 18 октября 2011

Как продолжение, в этом конкретном случае, если вы работаете на iOS, Apple рекомендует использовать UIColor и его метод -CGColor для возврата CGColorRef в colors NSArray.В примечаниях к выпуску Переход к ARC в разделе «Компилятор обрабатывает объекты CF, возвращенные из методов какао», указано, что использование метода, подобного -CGColor, который возвращает объект Core Foundation, будет автоматически обрабатываться.правильно компилятором.

Таким образом, они предлагают использовать код, подобный следующему:

CAGradientLayer *gradientLayer = (CAGradientLayer *)[self layer];
gradientLayer.colors = [NSArray arrayWithObjects:(id)[[UIColor darkGrayColor] CGColor],
                                                 (id)[[UIColor lightGrayColor] CGColor], nil];

Обратите внимание, что на данный момент в примере кода Apple отсутствует приведенный выше (id) приведенный код, что по-прежнему необходимо, чтобы избежать ошибки компилятора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...