¿Cómo reemplazo las referencias débiles cuando uso ARC y apunto a iOS 4.0?

87

Comencé a desarrollar mi primera aplicación para iOS con Xcode 4.2 y tenía como objetivo iOS 5.0 con una plantilla de "aplicación de utilidad" (la que viene con un FlipsideViewController).

Leí que dado que ARC es una función de tiempo de compilación, también debería ser compatible con iOS 4, así que intenté orientar mi aplicación a 4.3 e intentar compilarla. Cuando lo hago, aparece este error:

FlipsideViewController.m: error: Recuento automático de referencias Problema: el destino de implementación actual no admite referencias __ débiles automatizadas

Hace referencia a esta línea:

@synthesize delegate = _delegate;

Esa variable se declara como:

@property (weak, nonatomic) IBOutlet id <FlipsideViewControllerDelegate> delegate;

Entiendo que las "referencias débiles" no son compatibles con iOS 4, pero realmente no entiendo por qué querría usar una referencia débil para empezar, ni puedo averiguar cómo reescribiría las cosas para evitar usarlas, mientras todavía aprovechando ARC (después de todo, se supone que funciona con iOS 4 y 5, ¿verdad?)

Mason G. Zhwiti
fuente

Respuestas:

149

Para apuntar al sistema operativo más antiguo, puede usarlo en unsafe_unretainedlugar de weaken su declaración de propiedad, y en su mayoría debería funcionar de la misma manera. weaklas referencias se anulan cuando su objetivo desaparece, pero unsafe_unretaineddeja abierta la posibilidad de que el objeto al que está enlazando se convierta en un puntero colgante cuando se desasigne. Este último es el mismo comportamiento que si lo hubiera utilizado assigncomo declaración de propiedad en la gestión de memoria manual.

Haga esto para evitar retener ciclos, que menciono en mi respuesta aquí . No desea tener un puntero fuerte a algo que podría tener un puntero fuerte hacia el objeto original. Entonces nada se liberaría correctamente.

Brad Larson
fuente
Gracias por el consejo. Dices "para apuntar al sistema operativo más antiguo ...". ¿Significa esto que solo debería usar unsafe_unretained en versiones de la aplicación anteriores a 5.0? ¿O puedo usar unsafe_unretained en mi código y compilarlo para apuntar tanto a 4.xy 5.x?
Mason G. Zhwiti
1
@Mason: unsafe_unretainedes compatible con iOS 4.xy 5.0, por lo que le brinda compatibilidad con versiones anteriores. Si estaba haciendo una compilación de solo 5.0, puede cambiar a weakpara aprovechar la seguridad adicional que le brinda.
Brad Larson
Intenté unsafe_unretained, funcionó de todos modos. Sin embargo, recibí muchas advertencias como '"** __NSAutoreleaseNoPool (): Objeto 0x564bd90 de clase __NSArrayM liberado automáticamente sin un grupo en su lugar - solo goteando" *', ¿eso es normal?
quinto
1
@ quinta - Ese es un tema totalmente ajeno. Está ejecutando algo en un subproceso en segundo plano sin tener un grupo de liberación automática en su lugar. Los subprocesos creados manualmente no tienen su propio grupo de liberación automática, por lo que debe crear uno usted mismo utilizando @autoreleasepool(en ARC, NSAutoreleasePool para implementaciones más antiguas contadas manualmente).
Brad Larson
@Brad, eso es útil, las advertencias desaparecieron, recibí varias llamadas performSelectorInBackground.
quinto
11

Si solo usa referencias débiles para mayor seguridad, llame manualmente a las nuevas funciones de tiempo de ejecución si están disponibles y, si no, recurra a la asignación simple de __unsafe_unretainedvariables.

ZWRCompatibility.h simplificará esto un poco.

rpetrich
fuente
10

Gracias a la biblioteca de compatibilidad PLWeakCompatibilty de Mike Ash , ahora también puede usar __weak en iOS 4.x.

Es increíblemente fácil de configurar y no requiere consideración o esfuerzo adicional sobre 5.x.

nschum
fuente