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.
jest CFBridgingRetain tak samo jak (__bridge_retained void *) i CFBridgingRelease jako (__bridge_transfer MYObjCClass *)? – Dmitry
Tak, ale makra CFBridging * sprawiają, że jest bardziej oczywiste, co się dzieje. –
Świetnie. Wielkie dzięki, Rob. Teraz jest bardzo jasne – Dmitry