2

2つのパラメーターを使用してメインスレッドでセレクターを実行するための優れた方法を探しています

私は本当に使うのが好きです

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

メソッド、ただし今は2つのパラメーターがあります。

つまり、基本的に、画像が読み込まれたときに通知する必要のあるデリゲートがあります。

[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を使用していますか?前もって感謝します。

4

4 に答える 4

8

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

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

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

呼び出しをこれに置き換えれperformSelector:withObjectば、メソッド シグネチャを変更する必要がなくなります。

次のことを確認してください。

#import <dispatch/dispatch.h>

GCD サポートを導入します。

于 2011-12-25T12:38:17.797 に答える
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];
于 2011-12-25T20:10:33.363 に答える
2

次の方法も使用できます。

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

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

于 2011-12-25T12:34:15.170 に答える
1

はい、正しい考えをお持ちです。メイン スレッドでデリゲートに渡したいすべてのデータを、 を介して渡される 1 つのオブジェクトにカプセル化する必要がありますperformSelectorOnMainThreadNSDictionaryオブジェクト、NSArrayオブジェクト、またはカスタム Objective C オブジェクトとして渡すことができます。

于 2011-12-25T12:24:30.683 に答える