I came across this _cmd
trick:
-(void)methodToBeRunOnMainThreadWithObj:(id)object {
if (![NSThread isMainThread) {
[self performSelectorOnMainThread:_cmd withObject:object]
} else {
// ... method body
}
}
Is this a reliable way to ensure a method is performed on the main thread?
This works, but is a bit of an anti-pattern. What I would do is throw an error if the thread the method is called on is not the main thread. It is the responsibility of the caller to make sure methods are called on the right threads, these sorts of hacks only encourage ugly code. Besides, if you rely on this, suddenly you're doubling the message dispatch overhead for every time you call this method.
If you really cant change the caller's behavior, you can try the following:
-(void)methodToBeRunOnMainThreadWithObj:(id)object {
dispatch_sync(dispatch_get_main_queue(), ^{
// code goes here
});
}
this will cause all code inside the dispatch block to be executed on the main thread, and the method will not return until it is complete. If you want the method to return immediately, you can use dispatch_async
instead. If you use dispatch_sync
, you can use this trick even on methods that have non-void return types.
This code also has the added benefit of supporting methods with arguments that are of non-object types (int
etc). It also supports methods with an arbitrary number of arguments, whereas performSelector:withObject:
and its sibling methods only support a limited number of arguments. The alternative is to set up NSInvocation
objects and those are a pain.
Note that this requires Grand Central Dispatch (GCD) on your platform.
_cmd
forwarding is fine, as long as the selector specified by _cmd
matches the definition/signature specified in the documentation: "The method should not have a significant return value and should take a single argument of type id, or no arguments.". If it does not match, then you should assume Undefined Behavior. And to be 110% safe and to adhere to the abstract machine, the return type should be id
(or some objc-type), and the result should not return an owning reference.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With