2013-08-14 3 views
9

Мне нужно сохранить объект Objective C в указателе C struct in void *. Эта структура определена во внешней библиотеке, и я не могу изменить определение.Назначение объекта Objective-C в указателе void * с ARC

Допустим, она определяется как:

struct c_context { 
    void* user_data; 
}; 

и то, что мне нужно сделать в моем коде это:

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

Однако, мне нужно, чтобы убедиться, что MYObjCClass объект будет сохраняется.

Так что мой вопрос:

  1. Как бросить (или мост) его void* говорит компилятору, чтобы сохранить объект Obj-C?
  2. Как освободить объект позже, когда мне нужно очистить данные?

ответ

12

You cannot use ARC to manage an object in a struct. Вы несете ответственность за отслеживание управления памятью вручную. Таким образом вам не рекомендуется хранить объекты.

Если вы должны отслеживать модуля памяти таким образом, вы должны сказать, ARC, что вы принимаете на себя ответственность за объект, когда вы поместите его в структуры:

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

Это говорит ARC, что он больше не отвечает за объект возвращается init и добавляет руководство retain, так что context->user_data теперь является владельцем.

Когда вы закончите с объектом, вы можете либо перенести его обратно в ARC, либо вы можете его отпустить. Чтобы перевести его обратно в ARC:

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

Это говорит, что ARC несет ответственность за объект и удаляет ваше сохранение. Вы должны NULL указатель, потому что context->user_data больше не владеет этим объектом, и объект может исчезнуть в любое время.

Вы можете также непосредственно освободить его:

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

Опять же, это последний курорт техника. В общем случае вы не должны хранить объекты ObjC в структурах, поскольку ARC не может их управлять.

В качестве побочного примечания, хотя я обычно не рекомендую ObjC++, для автоматизации этого можно использовать структуру C++ с деструктором. В некоторых случаях это может быть предпочтительнее для управления памятью вручную в C.

+1

CFBridgingRetain то же, что и (__bridge_retained void *) и CFBridgingRelease as (__bridge_transfer MYObjCClass *)? – Dmitry

+1

Да, но макросы CFBridging * делают более очевидным то, что происходит. –

+0

Отлично. Большое спасибо, Роб. Теперь это очень ясно – Dmitry