2011-08-12 24 views
161

Con ARC, ya no puedo convertir CGColorRef en id. Aprendí que necesito hacer un reparto en puente. Según clang docs:ARC y molde en puente

Un puenteado fundido es un estilo de C elenco anotado con una de las tres palabras clave:

(__bridge T) op arroja el operando al tipo de destino T. Si T es un tipo de puntero de objeto retenible, entonces op debe tener un tipo de puntero no retenible . Si T es un tipo de puntero no retenible, , entonces op debe tener un tipo de puntero de objeto retenible. De lo contrario, el modelo está mal formado. No hay transferencia de propiedad, y las inserciones ARC no conservan las operaciones.

(__bridge_retained T) op arroja el operando, el cual debe tener retainable tipo puntero de objeto, para el tipo de destino, que debe ser un tipo de puntero no puede retener. ARC retiene el valor, sujeto a las optimizaciones habituales en valores locales, y el destinatario es responsable para equilibrar ese +1.

(__bridge_transfer T) op arroja el operando, el cual debe tener no puede retener tipo de puntero, al tipo de destino, que debe ser un tipo de puntero puede retener objeto . ARC lanzará el valor al final de la expresión completa adjunta, sujeto a las optimizaciones habituales en valores locales.

Estos moldes son necesarios para transferir objetos dentro y fuera del control ARC; consulte la explicación en la sección sobre conversión de punteros de objetos retenibles.

Usando un molde __bridge_retained o __bridge_transfer puramente para convencer ARC para emitir conservar un desequilibrado o liberación, respectivamente, es pobre forma.

¿En qué tipo de situaciones usaría cada una?

Por ejemplo, CAGradientLayer tiene una propiedad colors que acepta una matriz de CGColorRef s. Supongo que debería usar __brige aquí, pero exactamente por qué debería (o no debería) no está claro.

+17

has visto WWDC 2011 323 sesión todavía? Eso explica ARC mucho mejor de lo que podría aquí. Cubre todos los detalles de principio a fin. Es una sesión obligatoria para todos los desarrolladores de Mac/iOS. – rbrown

+0

Gracias, lo echaré un vistazo. – Morrowless

+0

Esto también podría ser de ayuda: http://stackoverflow.com/questions/14352494/bridged-cast-bridge-transfer-vs-bridge-with-synthesized-setter/28495303#28495303 –

Respuesta

212

Acepto que la descripción es confusa. Puesto que acabo las así, voy a tratar de resumir:

  • (__bridge_transfer <NSType>) op o alternativamente CFBridgingRelease(op) se utiliza para consumir una retener recuento de un CFTypeRef durante la transferencia de la vuelta a ARC. Esto también podría ser representado por id someObj = (__bridge <NSType>) op; CFRelease(op);

  • (__bridge_retained <CFType>) op o alternativamente CFBridgingRetain(op) se utiliza para entregar un NSObject a CF-tierra, mientras que le da un recuento de 1 conservan. Debe manejar un CFTypeRef que cree de esta manera igual que manejaría un resultado de CFStringCreateCopy().Esto también podría ser representado por CFRetain((__bridge CFType)op); CFTypeRef someTypeRef = (__bridge CFType)op;

  • __bridge simplemente se lanza entre pointer-land y Objective-C object-land. Si no tiene inclinación para usar las conversiones anteriores, use esta.

Quizás esto es útil. Yo prefiero las macros CFBridging… bastante más que las versiones planas.

+0

¿Los objetos retienen el recuento aumentan por arco por 1 cuando usas __bridge_transfer? De lo contrario, parecería que en el momento en que CFRelease() se llama el objeto desaparece y apunta a nada. De manera similar, cuando usa __bridge_retain, ¿ARC reduce el conteo de retención de la operación en 1? De lo contrario, parece que el objeto nunca se lanzaría correctamente. – Tony

+2

Una vez en tierra ARC ya no piensas en retener los conteos, solo en referencias fuertes y débiles. – monkeydom

+4

Sí, si solo estás en tierra de arco fuerte/débil sería suficiente, sin embargo, cuando estás haciendo la transición de objetos entre entornos de arco y no de arco, todavía tienes que pensar en las implicaciones de retención de conteo bajo el capó – Tony

32

Como seguimiento, en este caso específico, si tiene iOS, Apple recomienda utilizar UIColor y su método -CGColor para devolver el CGColorRef al colors NSArray. En el Transitioning to ARC Release Notes, en la sección "El compilador maneja los objetos CF devueltos desde métodos Cocoa", se indica que el compilador manejará automáticamente el objeto utilizando un método como -CGColor que devuelve un objeto Core Foundation.

Por lo tanto, ellos sugieren usar un código como el siguiente:

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

Tenga en cuenta que a partir de ahora, el código de ejemplo de Apple está perdiendo la (id) fundido tengo más arriba, que todavía es necesario para evitar un compilador error.

+0

Por lo general, puede salirse con la suya simplemente echando el primero de los objetos a (id) en lugar de todos ellos, si preferir. –

+1

Esta pregunta le pregunta sobre el casting con ARC, donde el código que ha pegado no es legal. –

+11

@JoeyHagedorn - Quizás se olvidó de mi referencia a la documentación de ARC en la primera frase de mi respuesta, pero esto no solo es válido en ARC, sino que es el enfoque recomendado para proporcionar referencias CGColorRef en NSArrays a partir de estos métodos de conversión UIColor. Yo, y muchos otros, uso este código exacto dentro de las aplicaciones habilitadas para ARC. La conversión inmediata a (id) de un método que devuelve un objeto Core Foundation conecta automáticamente ese objeto a ARC. –

51

he encontrado otra explicación en la documentación IOS que creo que es más fácil de entender:

  • __bridge transfiere un puntero entre Objective-C y la fundación de la base sin transferencia de la propiedad.

  • __bridge_retained (CFBridgingRetain) arroja un Objective-C puntero a una base fundamental puntero y también transfiere la propiedad a usted.

    Eres responsable para llamar a CFRelease o una función relacionada para renunciar a la propiedad del objeto.

  • __bridge_transfer (CFBridgingRelease) mueve un no Objective-C puntero a Objective-C y también transfiere la propiedad de ARC.

    ARC es responsable de por renunciar a la propiedad del objeto.

Fuente: Toll-Free Bridged Types