2013-08-14 18 views
9

Ho bisogno di mantenere un oggetto Objective C in una struttura C nel puntatore void *. Questa struttura è definita nella libreria esterna e non posso modificare la definizione.Assegnazione dell'oggetto Objective-C in un puntatore void * con ARC

Diciamo che è definita come:

struct c_context { 
    void* user_data; 
}; 

e quello che ho bisogno di fare nel mio codice è questo:

struct c_context *context; 
... 
context->user_data = [[MYObjCClass alloc] init]; 

Tuttavia, ho bisogno di fare in modo che l'oggetto MYObjCClass sarà mantenuto.

Quindi la mia domanda è:

  1. come lanciare (o ponte) a void* dice al compilatore di trattenere l'oggetto obj-c?
  2. Come rilasciare l'oggetto in un secondo momento quando è necessario pulire i dati?

risposta

12

You cannot use ARC to manage an object in a struct. L'utente è responsabile del monitoraggio della gestione della memoria manualmente. Sei scoraggiato dal memorizzare oggetti in questo modo.

Se è necessario monitorare la memoria in questo modo, si deve dire ARC che si sta assumendo la responsabilità per l'oggetto quando lo metti nella struct:

context->user_data = CFBridgingRetain([[MYObjCClass alloc] init]); 

Questo dice ARC che non è più responsabile è per la oggetto restituito da init e aggiunge un manuale retain in modo che context->user_data sia ora il proprietario.

Quando hai finito con l'oggetto, puoi trasferirlo di nuovo in ARC, oppure puoi rilasciarlo. Per ritrasferirlo su ARC:

MYObjCClass *something = CFBridgingRelease(context->user_data); 
context->user_data = NULL; 

Ciò indica a ARC che è responsabile per l'oggetto e rimuove il trattenimento. Si dovrebbe NULL il puntatore perché context->user_data non possiede più questo oggetto e l'oggetto potrebbe scomparire in qualsiasi momento.

Si può anche rilasciare direttamente esso:

CFRelease(context->user_data); 
context->user_data = NULL; 

Ancora una volta, questa è una tecnica di ultima istanza. In generale non si dovrebbero memorizzare oggetti ObjC nelle strutture dato che ARC non può gestirli.

Come nota a margine, anche se generalmente non raccomando ObjC++, è possibile utilizzare una struct C++ con un distruttore per automatizzarlo. In alcuni casi, potrebbe essere preferibile la gestione della memoria manualmente in C.

+1

CFBridgingRetain è uguale a (__bridge_retained void *) e CFBridgingRelease come (__bridge_transfer MYObjCClass *)? – Dmitry

+1

Sì, ma i macro CFBridging * rendono più evidente ciò che sta accadendo. –

+0

Grande. Grazie mille, Rob. Ora è molto chiaro – Dmitry

Problemi correlati