2013-08-14 8 views
9

Potrzebuję zachować obiekt Objective C w strukturze C w void * wskaźnik. Ta struktura jest zdefiniowana w bibliotece zewnętrznej i nie mogę zmienić definicji.Przypisywanie obiektu Object-C w pustym * wskaźniku z ARC

Powiedzmy, że jest zdefiniowany jako:

struct c_context { 
    void* user_data; 
}; 

i co muszę zrobić w moim kodu jest taka:

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

Jednak trzeba się upewnić, że obiekt MYObjCClass będzie zatrzymany.

Więc moje pytanie brzmi:

  1. Jak oddać (lub most) go void* mówienie kompilator zachować obiekt obj-c?
  2. Jak zwolnić obiekt później, gdy trzeba wyczyścić dane?

Odpowiedz

12

You cannot use ARC to manage an object in a struct. Jesteś odpowiedzialny za ręczne śledzenie zarządzania pamięcią. Odradza się przechowywanie przedmiotów w ten sposób.

Jeśli trzeba śledzić pamięć w ten sposób, trzeba powiedzieć ARC że przyjmuje odpowiedzialność za przedmiot po włożeniu go do struct:

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

Mówi ARC że nie jest już odpowiedzialny jest dla obiekt zwrócony przez init i dodaje instrukcję retain, dzięki czemu context->user_data jest teraz właścicielem.

Po zakończeniu pracy z obiektem można go przesłać z powrotem do ARC lub zwolnić. Aby przesłać go z powrotem do ARC:

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

To mówi ARC, że jest odpowiedzialny za obiekt i usuwa twoje zatrzymanie. Powinieneś NULL wskaźnik, ponieważ context->user_data nie jest już właścicielem tego obiektu i obiekt może zniknąć w dowolnym momencie.

Można również bezpośrednio zwolnić go:

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

Ponownie, jest to technika last resort. Zasadniczo nie należy przechowywać obiektów ObjC w strukturach, ponieważ ARC nie może nimi zarządzać.

Na marginesie, podczas gdy generalnie nie polecam ObjC++, można zautomatyzować to za pomocą struktury C++ z destruktorem. W niektórych przypadkach może to być lepsze niż ręczne zarządzanie pamięcią w C.

+1

jest CFBridgingRetain tak samo jak (__bridge_retained void *) i CFBridgingRelease jako (__bridge_transfer MYObjCClass *)? – Dmitry

+1

Tak, ale makra CFBridging * sprawiają, że jest bardziej oczywiste, co się dzieje. –

+0

Świetnie. Wielkie dzięki, Rob. Teraz jest bardzo jasne – Dmitry

Powiązane problemy