Com o ARC, não posso mais transmitir CGColorRef
para id
. Eu aprendi que preciso fazer um elenco em ponte. De acordo com clang docs :
Um elenco em ponte é um elenco no estilo C anotado com uma das três palavras-chave:
(__bridge T) op
lança o operando no tipo de destinoT
. SeT
é um tipo de ponteiro de objeto retido,op
deve ter um tipo de ponteiro não retido. SeT
for um tipo de ponteiro não retido, op deve ter um tipo de ponteiro de objeto retido. Caso contrário, o elenco está mal formado. Não há transferência de propriedade e o ARC não insere operações de retenção.
(__bridge_retained T) op
converte o operando, que deve ter o tipo de ponteiro de objeto retido, no tipo de destino, que deve ser um tipo de ponteiro não retido. O ARC retém o valor, sujeito às otimizações usuais nos valores locais, e o destinatário é responsável por equilibrar esse +1.
(__bridge_transfer T) op
converte o operando, que deve ter um tipo de ponteiro não retido, no tipo de destino, que deve ser um tipo de ponteiro de objeto retido. O ARC liberará o valor no final da expressão completa anexa, sujeito às otimizações usuais nos valores locais.Esses lançamentos são necessários para transferir objetos para dentro e fora do controle do ARC; veja a justificativa na seção sobre conversão de ponteiros de objetos retidos.
O uso de um
__bridge_retained
ou__bridge_transfer
elenco puramente para convencer o ARC a emitir uma retenção ou liberação desequilibrada, respectivamente, é uma forma ruim.
Em que tipo de situações eu usaria cada uma?
Por exemplo, CAGradientLayer
possui uma colors
propriedade que aceita uma matriz de CGColorRef
s. Meu palpite é que eu deveria usar __brige
aqui, mas exatamente por que eu deveria (ou não) não é claro.
fonte
Respostas:
Concordo que a descrição é confusa. Desde que eu as compreendi, tentarei resumir:
(__bridge_transfer <NSType>) op
ou, alternativamente,CFBridgingRelease(op)
é usado para consumir uma contagem de retenção de umCFTypeRef
enquanto a transfere para o ARC. Isso também pode ser representado porid someObj = (__bridge <NSType>) op; CFRelease(op);
(__bridge_retained <CFType>) op
ou, alternativamente,CFBridgingRetain(op)
é usado para entregar umNSObject
terreno CF, dando a ele uma contagem de retenção +1. Você deve lidar com um queCFTypeRef
você cria dessa maneira da mesma forma como lidaria com um resultadoCFStringCreateCopy()
. Isso também pode ser representado porCFRetain((__bridge CFType)op); CFTypeRef someTypeRef = (__bridge CFType)op;
__bridge
apenas projeta entre terra do ponteiro e terra do objeto C-objetivo. Se você não tem inclinação para usar as conversões acima, use esta.Talvez isso seja útil. Eu mesmo prefiro as
CFBridging…
macros um pouco do que os modelos simples.fonte
Encontrei outra explicação na documentação do iOS que acho mais fácil de entender:
__bridge
transfere um ponteiro entre Objective-C e Core Foundation sem transferência de propriedade.__bridge_retained (CFBridgingRetain)
lança um ponteiro Objective-C para uma Core Foundation e também transfere a propriedade para você.Você é responsável por chamar CFRelease ou uma função relacionada para renunciar à propriedade do objeto.
__bridge_transfer (CFBridgingRelease)
move um ponteiro não-Objective-C para Objective-C e também transfere a propriedade para o ARC.O ARC é responsável por renunciar à propriedade do objeto.
Fonte: Tipos de pontes gratuitas
fonte
Como conseqüência, nesse caso específico, se você estiver no iOS, a Apple recomenda usar o UIColor e seu
-CGColor
método para retornar o CGColorRef aocolors
NSArray. Nas notas de versão Transição para ARC , na seção "O compilador manipula objetos CF retornados de métodos de cacau", é indicado que o uso de um método como-CGColor
que retorna um objeto Core Foundation será automaticamente manipulado corretamente pelo compilador.Assim, eles sugerem o uso de código como o seguinte:
Observe que, no momento, o código de exemplo da Apple está ausente da conversão (id) que tenho acima, o que ainda é necessário para evitar um erro do compilador.
fonte