[myButton setEnabled:YES]
from a background thread
so it will execute on the main thread.
Alas, the obvious [myButton performSelectorOnMainThread:@selector(setEnabled:) withObject:(BOOL)YES waitUntilDone:YES];
is not only ugly, but also doesn't work.
It used to kinda sorta work for scalar integer/pointer parameters that fit in a register, but it
certainly wasn't a good idea and started breaking when Apple started to retain those parameters.
Casting a BOOL to a pointer and back might work at times, sending it a retain will definitely not.
What to do? Well, I would suggest the following:
[[myButton onMainThread] setEnabled:YES];
Not only does it handle the primitives without a sweat, it is also succinct and readable. It is obviously implemented using Higher Order Messaging (now with Wikipedia page), and I actually have a number of these HOMs in MPWFoundation that cover the common use-cases:
@interface NSObject(asyncMessaging)
-async;
-asyncPrio;
-asyncBackground;
-asyncOnMainThread;
-onMainThread;
-asyncOn:(dispatch_queue_t)queue;
-asyncOnOperationQueue:(NSOperationQueue*)aQueue;
-afterDelay:(NSTimeInterval)delay;
@end
There is a little HOM_METHOD() Macro that generates both the trampoline method and the worker method, so the following code defines the -(void)onMainThread method that then uses performSelectorOnMainThread to send the NSInvocation to the main thread:
HOM_METHOD(onMainThread) [invocation performSelectorOnMainThread:@selector(invokeWithTarget:) withObject:self waitUntilDone:YES]; }
You can use MPWFoundation as is or take the above code and combine it with Simple HOM.
No comments:
Post a Comment