2013-08-14 9 views
9

void * pointerのC構造体にObjective Cオブジェクトを保持する必要があります。この構造体は外部ライブラリで定義されており、定義を変更することはできません。void *ポインタにARCを指定してObjective-Cオブジェクトを割り当てる

のは、それは次のように定義されたとしましょう:

struct c_context { 
    void* user_data; 
}; 

と私は私のコードで行う必要があることはこれです:

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

はしかし、私はMYObjCClassオブジェクトがされることを確認する必要があります保持される。 OBJ-Cのオブジェクトを保持するようにコンパイラに伝えるvoid*

  1. キャスト(またはブリッジ)するためにどのように:

    だから私の質問はありますか?

  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; 

これは、オブジェクトに責任があり、あなたの保持を削除することを指示します。 context->user_dataはこのオブジェクトを所有しておらず、オブジェクトはいつでも消える可能性があるため、ポインタをNULLにする必要があります。また、直接それを解放することができます

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

は再び、これは最後の手段技術です。一般に、ARCはオブジェクトを管理できないため、ObjCオブジェクトを構造体に格納しないでください。サイドノートとして

私は、一般的にObjC++をお勧めしませんが、これを自動化するデストラクタとC++の構造体を使用することが可能です。いくつかの場合において、これは

+1

がAS(__bridge_retainedボイド*)と同じとCFBridgingReleaseをCFBridgingRetainさC.における手動のメモリ管理に好ましいであろう(__bridge_transfer MYObjCClass *)? – Dmitry

+1

はい、しかし、CFBridging *マクロは何が起こっているかをより明白にします。 –

+0

素晴らしいです。ありがとう、ロブ。今それは非常に明確です – Dmitry

関連する問題