最近、使用頻度が上がっている、performSelector。遅延実行もできるすぐれもの(遅延実行時の解放わすれは痛い目を見ます)ですが、私の場合は、NSNotificationCenter の代わり使うことが多くなってきました。
例えば、AVAudioPlayer では曲の終了時にイベントが発生しますが、そのイベントの後どこかに別のメソッドで処理をしたいときがあります。
そんな時は、こんな感じで記述してます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
-(void)setDidFinishPlayingHandler:(id)object selector:(SEL)selector withObject:withObj { handlerDelegate = object; handlerSelector = selector; handlerWithObject = withObj; } /* 曲が終了したら */ -(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { if (handlerSelector != NULL) { if ([handlerDelegate respondsToSelector:handlerSelector]) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks" [handlerDelegate performSelector:handlerSelector withObject:handlerWithObject ]; #pragma clang diagnostic pop } } } |
setDidFinishPlayingHandler:selector:withObject で 呼び出し先と引数を設定しておけば、曲が終わった時点で、perform (実行) してくれます。メモリ上に存在してるメソッドであればどこへでも行けるありがたさ。
しかし、最近、もう一つ利用頻度が上がっているクラスメソッドの場合はどうすればいいんだろうか。
例えば、現在表示中のViewControllerの インスタンスメソッド -(void)stopHandler: を呼び出したい時は
1 2 |
[self setDidFinishPlayingHandler:self selector:@selector(stopHandler:) withObject:nil]; |
とき記述します。しかし、クラスメソッドはインスタンス化されてないので、targetのクラスをどこにしていいのかわかりません。しかし、いつでも呼び出せるということはメモリ上には存在しているはずなので、その方法はあるはずです。いや、あるのです。
仮に クラスメソッド +(void)pauseHandeler: 、クラスが classSound だった場合はこんな感じで呼び出せます。
1 2 |
[self setDidFinishPlayingHandler:[classSound class] selector:@selector(pauseHandeler:) withObject:nil]; |
なんてことでしょうか、NSObject に クラスメソッド +(Class)class があり、class object を返してくれるのです。
この場合だと、 [classSound class] を target にすることで、その内部にある+(void)pauseHandeler:、を呼び出すことに成功出来ました。 ありがたやありがたや。
コメント