2011-12-25 6 views
2

私は本当に今、私は2つのパラメータを持っている除く2つのパラメータを使ってメインスレッドでセレクタを実行する良い方法はありますか?

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait 

方法を、使用してのような二つのパラメータ

Iとメインスレッドでセレクタを実行するための良い方法を探しています。

だから基本的に私は、私はイメージがロードされたときに通知する必要がデリゲートを持っている:

[delegate imageWasLoaded:(UIImage *)image fromURL:(NSString *)URLString; 

しかし、私はこれを行う方法は、バックグラウンドスレッドで呼び出されるかもしれない、とデリゲートがこの画像を使用しますUIを更新するには、これをメインスレッドで行う必要があります。だから私は本当にデリゲートがメインスレッドで通知されるようにしたい。

私は1つのオプションを参照しています - 私は渡す必要がある2つのパラメータを含む1つだけのオブジェクトを持つこの方法で、辞書を作成することができます。

NSDictionary *imageData = [NSDictionary dictionaryWithObjectsAndKeys:image, @"image",  URLString, @"URLstring", nil]; 
[(NSObject *)delegate performSelectorOnMainThread:@selector(imageWasLoaded:) withObject: imageData waitUntilDone:NO]; 

しかし、このアプローチは私には当てはまりません。これを行うよりエレガントな方法はありますか?おそらくNSInvocationを使用していますか? ありがとうございます。

答えて

6

GCDにアクセスできないので、ここではNSInvocationが最適です。

NSMethodSignature *sig = [delegate methodSignatureForSelector:selector]; 
NSInvocation *invoke = [NSInvocation invocationWithMethodSignature:sig]; 
[invoke setTarget:delegate]; // argument 0 
[invoke setSelector:selector]; // argument 1 
[invoke setArgument:&arg1 atIndex:2]; // arguments must be stored in variables 
[invoke setArgument:&arg2 atIndex:3]; 
[invoke retainArguments]; 
    /* since you're sending this object to another thread, you'll need to tell it 
    to retain the arguments you're passing along inside it (unless you pass 
    waitUntilDone:YES) since this thread's autorelease pool will likely reap them 
    before the main thread invokes the block */ 

[invoke performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:NO]; 
+0

これは正しい解決策GCDです。これが頻繁に使用されるなら、簡単にカスタムメソッド 'performSelectorOnMainThread:withObject:withObject:'に入れることができます。 –

+0

ありがとうございました!これは私が探していたものです – dariaa

+0

使用後に何かをリリースする必要がありますか(引数は保持されているため) – b123400

1

はい、正しいアイデアがあります:メインスレッドのデリゲートに渡すすべてのデータを、performSelectorOnMainThreadで渡される1つのオブジェクトにカプセル化する必要があります。 NSDictionaryオブジェクト、またはNSArrayオブジェクト、またはカスタムObjective Cオブジェクトとして渡すことができます。この方法を使用することも可能に続き

1

- (id)performSelector:(SEL)aSelector withObject:(id)anObject withObject:(id)anotherObject 

このMETHOD- のドキュメントを1としては、遅延の後にデフォルトモードを使用して、現在のスレッド上のレシーバのメソッドを呼び出します。

+1

しかし、問題は、私はそれが私の心に出くわしたメインスレッド、それは – dariaa

8

この場合、NSDictionaryを使用して複数のパラメータを渡すのが正しい方法です。

しかし、もっと現代的な方法は、GCDとブロックを使用することです。この方法では、メッセージをオブジェクトに直接送信できます。また、デリゲートメソッドが何かUI更新を行っているかのように見えます。メインスレッドで正しく処理しています。 GCDを使えば、簡単にこれを行うには、非同期でこのようなことができます。

dispatch_async(dispatch_get_main_queue(), ^{ 
    [delegate imageWasLoaded:yourImage fromURL:yourString; 
}); 

は、これであなたのperformSelector:withObjectコールを交換し、あなたのメソッドのシグネチャを変更することで周りの混乱する必要はありません。

ご確認してください:

#import <dispatch/dispatch.h> 

GCDサポートに持参します。

+0

おかげで多くを呼び出されたスレッドに関係なく、中に送信されるようにしたいということですが、私の展開OSは3.0で、IドンiOS 4.0と3.0用に異なるコードを書こうとしていません。 NSInvocationについては、ここで使用できますか? – dariaa

+0

本当ですか? 2つのOSは現在のものの後ろにありますか?これを反映するようにタグを更新しました。しかし、新しいアプリを起動していて、iOS3用に書いた理由がない場合は、可能な限り最新のSDKを作成する方がよいでしょう。 – Abizern

+0

残念ながら、残念ながらそれは私の決定ではありません:( – dariaa

関連する問題