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), которое все еще необходимо, чтобы избежать ошибки компилятора.