Using _cmd to execute a method in the main thread in a c object

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 that the method runs in the main thread?

+7
source share
2 answers

This works, but a bit anti-pattern. I would make a mistake if the thread called by the method is not the main thread. The responder must make sure that the methods are invoked on the correct threads, these types of hacks only encourage ugly code. In addition, if you rely on this, suddenly you double the overhead of sending messages each time you call this method.

If you really cannot 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 the code inside the sending block to be executed in the main thread, and the method will not return until it is completed. If you want the method to return immediately, you can use dispatch_async . If you use dispatch_sync , you can use this trick even in those methods that have non-empty return types.

This code also has the added benefit of supporting methods with non-object arguments ( int , etc.). It also supports methods with an arbitrary number of arguments, while performSelector:withObject: and its sibling methods only support a limited number of arguments. An alternative is to create NSInvocation objects, and that is a pain.

Please note that this requires the Grand Central Dispatch (GCD) on your platform.

+7
source

_cmd forwarding is fine if the selector specified by _cmd matches the definition / signature specified in the documentation: "The method must not have a meaningful return value and must accept a single argument of type id, or no arguments.". If this does not match, you should accept Undefined Behavior. And in order to be 110% safe and stick to an abstract machine, the return type must be id (or some objc type), and the result should not return a reference to the owner.

+3
source

All Articles