objective c - strong @property con__attribute__((NSObject)) para un tipo de CF no se conserva
objective-c ios (1)
EDIT2 (Mar 2013) Para su información fiscal para aquellos interesados en esta técnica, la documentación ARC para el sonido incluye la siguiente nota:
No se recomienda el uso de
__attribute__((NSObject))
. Si es absolutamente necesario usar este atributo, sea muy explícito acerca del uso de typedef, y no suponga que lo conservarán las características del lenguaje como__typeof
y la sustitución de argumentos de la plantilla de C ++.Razón fundamental
Cualquier operación de compilación que accidentalmente elimine el tipo "azúcar" de un tipo producirá un tipo sin el atributo, lo que puede resultar en un comportamiento inesperado.
EDITAR Lo siguiente es interesante, pero probablemente irrelevante. Esto es un error y deberías abrir un radar. Como lo señaló @lnafziger, esto es legal y se supone que debe ser respetado. El error es que no se cumple cuando se incluye nonatomic
. Si eliminas no nonatomic
, entonces funciona. Nada en la definición no nonatomic
sugiere que esto sea por diseño.
Esto es algo inteligente, pero creo que veo por qué no funciona. Puede confirmar, por cierto, que no está funcionando generando el ensamblador y observando que setStr:
no llama a objc_storeStrong()
. Hace una simple tarea.
El problema es que la definición de su propiedad no se ajusta a la definición de un puntero de objeto retenible (énfasis agregado):
Un puntero de objeto retenible (o puntero retenible) es un valor de un tipo de puntero de objeto retenible (tipo retenible). Hay tres tipos de tipos de punteros de objetos que se pueden volver a organizar:
- punteros de bloque (formados por la aplicación del símbolo de intercalación (^) a un tipo de función)
- Punteros de objeto Objective-C (id, Class, NSFoo *, etc.)
- typedefs marcados con __attribute __ ((NSObject))
¿Creó un typedef como se especifica? No, no lo hiciste. OK, entonces, ¿cómo haríamos esto?
typedef __attribute__((NSObject)) CFStringRef MYStringRef;
@interface TestClass : NSObject
@property (nonatomic, strong) MYStringRef str;
@end
... the rest of your code ...
Esto imprimirá "1" y luego "2" como supongo que espera. Me asusta por razones no especificadas, pero mirando la salida del ensamblador, todo parece estar bien y no puedo pensar en ningún problema específico o violación aquí.
Podrías estar justificado en abrir un radar para esto. El hecho de que un typedef no se trate de la misma manera que un tipo especificado es sorprendente, al menos, aunque esté documentado.
EDITAR: Teniendo en cuenta el comentario de @ lnafziger del lenguaje de programación ObjC , definitivamente hay un error en la especificación / implementación de ARC o un error en el documento vinculado, por lo que uno de ellos debe ser reparado.
ACTUALIZACIÓN: ¡Este problema se ha solucionado a partir de Xcode 4.6!
Esta técnica ahora funciona según lo previsto de nuevo. Sin embargo, asegúrese de leer las notas en la parte superior de la excelente respuesta de Rob Napier antes de usarla en su código.
POSTE ORIGINAL
(ARC, Xcode 4.3.1, iOS 5.1)
Tengo una fuerte propiedad de un tipo de CF (CGImage) que quiero que ARC administre automáticamente usando __attribute__((NSObject))
(como mantener y liberar en el configurador sintetizado, y no tenerlo en dealloc), pero no funciona: el objeto no se conserva cuando asigno la propiedad.
Un ejemplo mínimo para reproducir:
@interface TestClass : NSObject
@property (nonatomic, strong) __attribute__((NSObject)) CFStringRef str;
@end
// ...In some function
CFStringRef str = (__bridge CFStringRef)[NSString stringWithFormat:@"%g", 2.5];
NSLog(@"%ld", CFGetRetainCount(str));
TestClass *obj = [[TestClass alloc] init];
obj.str = str;
NSLog(@"%ld", CFGetRetainCount(str));
Que imprime ''1'' dos veces.
Ahora lo extraño es que (aunque no estoy seguro de esto) creo que funcionó correctamente antes de actualizar a iOS 5.1 y Xcode 4.3.1 (de iOS 5 y Xcode 4.2), y con esto cambió de gdb a lldb. ¿Alguien que no haya actualizado (o sepa cómo volver a cambiar el compilador) quizás confirme?