Reputation: 126085
I'd like to call (void)setDoubleValue:(double)value
using performSelectorOnMainThread:
.
What I thought would work is:
NSNumber *progress = [NSNumber numberWithDouble:50.0];
[progressIndicator performSelectorOnMainThread:@selector(setDoubleValue:)
withObject:progress
waitUntilDone:NO];
Didn't work.
Then I implemented a helper method:
- (void)updateProgressIndicator:(NSNumber *)progress
{
[progressIndicator setDoubleValue:[progress doubleValue]];
}
Works, but not really clean.
After that I tried it with 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];
This solution works, but it uses a lot of code and is quite slow. (Even if I store the invocation.)
Is there any other way?
Upvotes: 3
Views: 3541
Reputation: 100
This blog post: http://www.cimgf.com/2008/03/01/does-objective-c-perform-autoboxing-on-primitives/ points out that while Cocoa won't autobox primitives, it will unbox them automatically. So numbers and BOOLs at least can be passed in as an NSNumber class, and the called function will automatically unbox it. I've been playing with using a proxy object (Uli's UKMainThreadProxy*) which works quite well, although I'm sure it has it's limitations like anything else.
Upvotes: -2
Reputation: 170309
Dave Dribin has a solution for this that takes the shape of a category on NSObject. His category wraps the method call in an NSInvocation and invokes that on the main thread. This way, you can use whatever method interface you like, including primitive types for your arguments.
The Amber framework also has a category on NSObject that adds a main thread proxy, where any messages sent to that proxy are executed on the main thread.
Upvotes: 2
Reputation: 162712
If you are on Snow Leopard, you can use Blocks:
dispatch_async(dispatch_get_main_queue(), ^{
[progressIndicator setDoubleValue: 50.0];
});
Upvotes: 9
Reputation: 85522
you'll need to write a custom un-boxing method to wrap setDoubleValue:.
- (void) setDoubleValueAsNumber: (NSNumber *) number {
[self setDoubleValue: [number doubleValue]];
}
Upvotes: 7