如何使用performSelectorOnMainThread的本机C类型:?

时间:2009-09-16 13:50:26

标签: objective-c cocoa multithreading

我想使用(void)setDoubleValue:(double)value致电performSelectorOnMainThread:

我认为可行的是:

NSNumber *progress = [NSNumber numberWithDouble:50.0];
[progressIndicator performSelectorOnMainThread:@selector(setDoubleValue:)
                                    withObject:progress
                                 waitUntilDone:NO];

没用。

然后我实现了一个辅助方法:

- (void)updateProgressIndicator:(NSNumber *)progress
{
    [progressIndicator setDoubleValue:[progress doubleValue]];
}

有效,但不是很干净。

之后我用NSInvocation尝试了它。

NSInvocation *setDoubleInvocation;;
SEL selector = @selector(setDoubleValue:);
NSMethodSignature *signature;
signature = [progressIndicator methodSignatureForSelector:selector];
setDoubleInvocation = [NSInvocation invocationWithMethodSignature:signature];
[setDoubleInvocation setSelector:selector];
[setDoubleInvocation setTarget:progressIndicator];

double progress = 50.0;
[setDoubleInvocation setArgument:&progress atIndex:2];

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

此解决方案有效,但它使用了大量代码并且速度很慢。 (即使我存储了调用。)

还有其他办法吗?

4 个答案:

答案 0 :(得分:9)

如果您使用Snow Leopard,则可以使用Blocks:

dispatch_async(dispatch_get_main_queue(), ^{
    [progressIndicator setDoubleValue: 50.0];
});

答案 1 :(得分:7)

你需要编写一个自定义的非装箱方法来包装setDoubleValue:。

- (void) setDoubleValueAsNumber: (NSNumber *) number {
   [self setDoubleValue: [number doubleValue]];
}

答案 2 :(得分:2)

Dave Dribin有一个solution for this,它在NSObject上具有类别的形状。他的类在NSInvocation中包装方法调用,并在主线程上调用它。这样,您可以使用您喜欢的任何方法接口,包括参数的基本类型。

Amber framework在NSObject上也有一个类别,它添加了一个主线程代理,发送到该代理的任何消息都在主线程上执行。

答案 3 :(得分:-2)

这篇博客文章:http://www.cimgf.com/2008/03/01/does-objective-c-perform-autoboxing-on-primitives/指出,虽然Cocoa不会自动装箱原语,但它会自动取消装箱。所以数字和BOOL至少可以作为NSNumber类传递,被调用的函数将自动取消它。我一直在使用代理对象(Uli的UKMainThreadProxy *),它工作得很好,虽然我确信它有其他任何限制。