2

我正在寻找一种在主线程上使用两个参数执行选择器的好方法

我真的很喜欢使用

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

方法,除了现在我有两个参数。

所以基本上我有一个委托,我需要在加载图像时通知它:

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

但是我这样做的方法可能会在后台线程中调用,并且委托将使用此图像来更新 UI,所以这需要在主线程中完成。所以我真的希望委托也能在主线程中得到通知。

所以我看到了一个选项——我可以创建一个字典,这样我只有一个对象,其中包含我需要传递的两个参数。

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

是的,您的想法是正确的:您需要将要传递给主线程上的委托的所有数据封装到一个对象中,该对象通过performSelectorOnMainThread. 您可以将其作为NSDictionary对象、NSArray对象或某些自定义的 Objective C 对象传递。

于 2011-12-25T12:24:30.683 回答