2010-12-11 7 views
2

簡単なプログラム:performSelectorのカウントを保持への影響:withObject:afterDelay:inModes

-(void)doSomething { 

NSLog(@"self rc=%d", [self retainCount]); 

[self performSelector:@selector(doMe:) withObject:nil afterDelay:0 inModes:[NSArray arrayWithObject:NSDefaultRunLoopMode]]; 

NSLog(@"self rc=%d", [self retainCount]); 
} 

-(void)doMe:(id)object { 

NSLog(@"i'm done"); 

NSLog(@"self rc=%d", [self retainCount]); 

} 

出力:

self rc=1 

self rc=2 

i'm done 

self rc=2 

なぜにカウント増分を保持し、2に滞在しますか?

+0

doMeが終了したときの保持カウントは何ですか? – nacho4d

答えて

13

-[NSObject performSelector:withObject:afterDelay:inModes:] documentation

2013年11月1日の回答ドキュメントが更新されるように見える

、予想通り、今、彼らはしかし、彼らはまだ言及ターゲットオブジェクトが保持されて言っていませんrunloopの予定タイマー。

NSTimerが使用されている場合、オブジェクトは誰かによって保持されなければなりません。また、オブジェクトがまだ生存していることを誰も保証できないため、セレクタを実行できる保証はありません。 ARCのweakを使用しない場合、クラッシュします。 私の意見では、Appleは実装の詳細は言及していませんが、ドキュメントを編集しましたが、かなり分かりやすいと思います。

上記の文書では、の保持はすべてとは言いませんが、ターゲットが保持されているわけではありません。

(lldb) p (int)[self retainCount] 
(int) $1 = 8 
(lldb) expr (void)[self performSelector:@selector(description) withObject:nil afterDelay:1.0] 
(lldb) p (int)[self retainCount] 
(int) $2 = 9 
(lldb) expr (void)[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(description) object:nil] 
(lldb) p (int)[self retainCount] 
(int) $3 = 8 

結論::オブジェクトが保持されますが、それは我々が気にすべきものではありません

これは、私はシミュレータiOS7.0でのデバッガで試行するものです。 ミスターは解決:P


前回答:を(まだ有効)

選択が行われる 後まで、この方法は、受信機と anArgumentパラメータを保持します。

オブジェクトが保持されないと、オブジェクトが実行される前に解放され、アプリケーションがクラッシュする可能性があるためです。

NSTimersを使用してメソッドを設定して起動しようとするときと同じロジックです。ターゲットオブジェクトがもう存在しない(リリースされている)場合、タイマーが実際に起動されると、アプリがクラッシュします。だから、performSelector:withObject:afterDelay:...と、それは、タイマーが起動されたときにアプリがクラッシュしていないと確信してますので、その友人は、私たちの生活が少し楽にするためにここにいる;)

は、それはあなたが間違っていることを信じているように見える

+0

docポインタをありがとう。それは質問に答えて理にかなっています。 – Ruug

+0

こんにちは、リンク先の文書は、あなたの明細書に同意しないでください。 NSObjectの一部である "performSelector"のバリエーションがあり、それらのドキュメントにはレシーバやオブジェクトを保持することについて何も言われていません。 NSRunloopメソッドperformSelectorのみが、ターゲットとオブジェクトの両方を保持するように文書化されています。ご注意くださいませ。 –

+0

@MottiShneor彼はNSSTimersを含むメッセージを明示的に述べました。 performSelectorの残っている束は、タイマーの –

4

を役に立てば幸いdoMe:のNSLogは、doSomething:の2番目前のNSLogを実行します。それは間違っている。 performSelector:afterDelay:…の方法では、遅延が0であってもrunloopを使用してメッセージがスケジュールされるため、次のrunloopの繰り返しで実行されます。

これ以外にも、オブジェクトの保持カウントを調べるのは正当な理由がありません。あなたが見た場合、あなたが見たものを信用しないでください。retainCountメソッドの結果は、最高で混乱し、最悪の場合は完全に欺瞞的です。明白で非常に一般的な例では、保持カウントにオートリースが反映されません。

+1

保持カウントを見ていないことについて助言をいただき、ありがとうございます。私はそれが参考になるかもしれないと思う制御された例でそれを見て、おそらくデバッグツールとしてではない。 – Ruug

+0

私はチャックと部分的に同意しますが、retainCountを使用すると、オブジェクトが保持されるかどうかわからないため、自分で計算した値と比較すると混乱する可能性があります。しかし、私はそれがオブジェクトのライフサイクルをチェックする良い方法だと思います。オブジェクトのretainCountがXの場合、オブジェクトで何かを行うと(その保持数が変わる可能性があります)、その後、retainCountが再びXに戻るはずです。この場合のように、performSelector ...の前とdoMe:retainCountの後には、どういうことがわかりませんが、確かに同じです。 – nacho4d

+0

@ nacho4d:あなたはあなたがひどく間違っているのに加えて、何を言いたいのか分からない。 Autoreleaseだけでは、「私は何をやっていたのか、その時は...そのretainCountはXに戻ってくるはずです」という記述が不正確になる。オブジェクトが解放されずにオートリリースされる場合、オブジェクトの保持カウントはしばらく上昇します。ドキュメントでは、 'retainCount'メソッドが有益な情報をもたらすとは言えません:http://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/Reference/NSObject.html #// apple_ref/occ/intfm/NSObject/retainCount – Chuck

関連する問題