2011-01-12 12 views
0

ObjectiveC - オブジェクトをパラメータとして追加して解放します。

Java開発者である私はまだObjectiveCのメモリ管理に苦労しています。私はすべての基本をカバーしていますが、しばらくして私は挑戦に遭遇します。 MyObjectクラスのコンストラクタは、私はオンザフライ開始タイプMyParameterObjectのパラメータを取り

MyObject myObject = new MyObject(new MyParameterObject()); 

:私は何をしたいか

は、Javaで次のようになりますものです。これは私に実際に発生しMyParameterオブジェクトに対して警告「オブジェクトの潜在的な漏れ」を与えるツールのビルドを実行している、しかし

MyObject *myObject = [[MyObject alloc] init:[[MyParameterObject alloc] init]]; 

と分析:ObjectiveCで

は、私は、この使用して、次のコードを実行しようとしました私はInstrumentsを使ってそれをテストします。私は allocメソッドを使ってオブジェクトの所有権を取得しており、放棄していないので、なぜこのようなことが起こるのか理解しています。正しい方法はわかりません。 は私が
MyObject *myObject = [[MyObject alloc] init:[[[MyParameterObject alloc] init] autorelease]]; 

を使用してみましたが、その後の分析ツールは、「オブジェクトが何回も-autorelease送ら」と言ってくれました。

return self;の代わりに、MyParameterObjectinitメソッドをreturn [self autorelease];と変更して問題を解決できました。 Analyzeは依然として潜在的なリークについて警告しますが、実際には発生しません。しかし、私はこのアプローチがObjectiveCのメモリを管理するための規約に違反していると確信しています。

Thanx事前に。

答えて

3

ここに提案があります。

MyParameter *param = [[MyParam alloc] init]; 
MyObject *obj = [[MyObject alloc] initWithParam:param]; // do you know if param is retain'd or not? 
[param release]; 

なぜこのようになりますか?これは、ObjC/Cocoa全体で使用されるパターンです。あなたはNSArraysにこの方法をオブジェクトを追加します。

MyThing *thing = [[MyThing alloc] init]; 
[myMutableArray addObject: thing]; // this calls [thing retain] 
[thing release]; 

ます。また、これを実行しようとすることもできます。

MyObject *obj = [[MyObject alloc] initWithParam: [MyParameter parameter]]; 

:あなたが心配する必要はありません道

+ (id) parameter 
{ 
    return [[[self alloc] init] autorelease]; 
}  

それについて。これは

[NSData data]; 
[NSArray array]; 

と同じです。一般的には、別のメソッド呼び出し(セッターや別のinitなど)でinitを使用することはお勧めできません。クラスメソッド(+ (id) parameter)の後ろにそれを隠すと、ユーザーはそれがautorelease 'dであることを知っています。


[EDIT]

警告:どうやらあなたshould never use -retainCountあなたが持っているどのように多くのretain年代やreleaseの何かについて、これまで不明確であれば

は、あなたは常にこのような何かを行うことができます。私はそれが学習者にretainのメモリ管理の基礎を教えるのに有益だと思っていますが、その要点はよく取られています。

Never Use it in actual code or for performance testing.これは、retainが何であるかを知るためにのみ使用されます(この場合、正しく機能すると思います)。それはあなたのNSArrayまたはその他財団/ AppKitの/ UIKitのクラス

MyParameter *param = [[MyParam alloc] init]; 
NSLog(@"param retain count: %d",[param retainCount]); // should be 1 
MyObject *obj = [[MyObject alloc] initWithParam:param]; 
NSLog(@"param retain count: %d",[param retainCount]); // should be 2, if MyObject retains it. 
[param release]; 
NSLog(@"param retain count: %d",[param retainCount]); // should be 1 

また、あなたがdealloc MyObjectに、によってdをautoreleaseretain Dまたはさらに」であるオブジェクトのためのインテリジェントな答えを与えることはありません初期化中にretainの場合、releaseパラメータが必要になります。

アップル社の次のguideは、Objective-Cメモリ管理の理解を深めるのに役立ちます。

+0

あなたが提案した最初のアプローチを使用してやります。私はそれについて自分自身について考えていたが、あなたの(全体の)答えは私に確信した。私はちょうど私がJavaとC#から常にObjectiveCで動作していないものをやっていることを行う "怠惰な"方法のいくつかを受け入れる必要があると思います: – pajevic

+1

+1正しい、**あなたは決して使用しないでください ' -retainCount'、何でもいい理由** –

+0

@NobleK、残念ながら。客観的なCは非常に、非常に言葉です。そして、個々のメソッドに対して単一のメソッド呼び出しを持つことは非常に好きです。また、アップルが行っているのと同じパターンのコードを使用することで、Analyzeツールを混乱させることはありません。 –

0
MyObject *myObject = [[MyObject alloc] init:[[[MyParameterObject alloc] init] autorelease]]; 

は、initにリリースが存在しない場合はokです(initにリリースされていないはずです)。私はしばしばオートレリースされたオブジェクトを作るクラスメソッドを作る。だから、コードは次のようになります。

// using it: 
MyObject *myObject = [[MyObject alloc] init:[MyParameterObject defaultParameters]; 

// in the class implementation of MyParameterObject 
+ (MyParameterObject*) defaultParameters{ 
    MyParameterObject* out = [[MyParameterObject alloc] init]; 
    // set some values 
    return [out autorelease]; 
} 
+0

codelarkの回答と同じです。 – pajevic

2
MyThing *thing = [[MyThing alloc] init]; 
[otherThing methodWithAThing:thing]; 
[thing release]; 

か:

[otherThing methodWithAThing:[[[MyThing alloc] init] autorelease]]; 

または(あなたが使用しているクラスの "簡易コンストラクタ" がある場合):

[otherThing methodWithAThing:[MyThing thing]]; 
+0

ええ、autoreleaseは正常に動作するはずですが、なぜ私がAnalyzeで警告を受け取るのか理解できません。私は実際にこれらの呼び出しの多くを持っているので、私はパラメータの変数を作ることを避けたい。便利なコンストラクタは、パラメータオブジェクトの実際のinitがパラメータ(int)自体を持っているため(私は思う)、どちらも可能ではありません(私はこの例では単純にしていました)。 – pajevic

0
[[MyObject alloc] init:[[[MyParameterObject alloc] init] autorelease]] 

initメソッドで何が起こっているかわからなくても、これは問題ありません。

NBでも、この "initWithParameterObject:"を綴るのはObjective-Cishです。 Obj-Cの記述方法の名前は、実際にはコードの読みやすさに役立ちます。

+0

initメソッドは正常に見えます(そこには何かの自動解放はありません)。分析がなぜ警告を出すのか分かりません。私は命名規則について知っています。最初は苦労しましたが、私は今それらを感謝しています:)上記の例を可能な限りJavaの例に似せようとしました。 – pajevic

+0

@NobleK、残念ながら、JavaとObj-Cの間のメモリ管理は非常に異なっているため、それらを「似ている」とすると、暗い欲求不満のパスにつながります! 'alloc/init'は' new'のようなものではありません。代わりにiPhoneの例からコードをパターニングしてみてください。 - [Ray Wenderlich](http://www.raywenderlich.com/)には良いものがたくさんあります。 –

+0

@NobleK - Clangは良い仕事をしていますが、間違いがあります。たとえば、非同期作業を行い、デリゲートを呼び出すと、それをキャッチしてデリゲートコールで解放することができますが、Clangはそれに従うことができず、オブジェクトの最後に潜在的なリークを呼び出しますインスタンス化されたブロック... –

関連する問題