dar*_*iaa 2 multithreading objective-c selector nsinvocation ios-3.x
我正在寻找一种在主线程上使用两个参数执行选择器的好方法
我真的很喜欢用
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait
Run Code Online (Sandbox Code Playgroud)
方法,除了现在我有两个参数.
所以基本上我有一个委托,我需要在加载图像时通知:
[delegate imageWasLoaded:(UIImage *)image fromURL:(NSString *)URLString;
Run Code Online (Sandbox Code Playgroud)
但是我可以在后台线程中调用我执行此操作的方法,并且委托将使用此图像来更新UI,因此需要在主线程中完成.所以我真的希望代理在主线程中得到通知.
所以我看到一个选项 - 我可以创建一个字典,这样我只有一个对象,它包含两个我需要传递的参数.
NSDictionary *imageData = [NSDictionary dictionaryWithObjectsAndKeys:image, @"image", URLString, @"URLstring", nil];
[(NSObject *)delegate performSelectorOnMainThread:@selector(imageWasLoaded:) withObject: imageData waitUntilDone:NO];
Run Code Online (Sandbox Code Playgroud)
但这种方法对我来说似乎不对.有没有更优雅的方式来做到这一点?也许使用NSInvocation?提前致谢.
在这种情况下,使用NSDictionary传递多个参数是正确的方法.
但是,更现代的方法是使用GCD和块,这样您就可以直接向对象发送消息.此外,看起来您的委托方法可能正在做一些UI更新; 您正在主线程上正确处理.使用GCD,您可以轻松地执行此操作,并且可以像这样异步执行:
dispatch_async(dispatch_get_main_queue(), ^{
[delegate imageWasLoaded:yourImage fromURL:yourString;
});
Run Code Online (Sandbox Code Playgroud)
performSelector:withObject用这个替换你的电话,你不必乱用改变你的方法签名.
确保你:
#import <dispatch/dispatch.h>
Run Code Online (Sandbox Code Playgroud)
引入GCD支持.
由于您无法访问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];
Run Code Online (Sandbox Code Playgroud)