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

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

Приведение с мостовым соединением - это приведение в стиле 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 ответа

Решение

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

  • (__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… макросы совсем немного по простому приведению.

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

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

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам