Monday, October 9, 2017

What does performSelector do? What is the difference between creating a new NSThread and the performSelector method?

All of these perform the same task, that is make the doStuff method on anObject execute synchronously on the current thread:

// 1
[anObject doStuff];

// 2
[anObject performSelector:@selector(doStuff)];

// 3
objc_msgSend(anObject, @selector(doStuff));

// 4
IMP imp = [anObject methodForSelector:@selector(doStuff)];imp(anObject, @selector(doStuff));

  1. Is how you normally should go about to do stuff.
  2. Is for dynamically dispatching a message. Use if the selector is unknown, or provided by a client, for example if you implement an target-action pattern. or if the class of anObject is unknown, usually used by first asking if the object has the method with -[NSObject respondsToSelector:].
  3. Is what no 1. is actually compiled down to. Usually never any real need to do this.
  4. Cached the actual IMP (implementation) for a method, and then call it directly. Can sometimes be faster than 1. if used in a tight loop. Just remember; premature optimization is evil.
What you need to grasp is that in Objective-C methods are more important than classes/interfaces. Usually you do not query an object if it belongs to a particular class, or conforms to any protocol, that is for the compiler to complain about. At run-time you instead query for specific methods.

In short: It does not matter what you are, just what you can do.

As a convenience NSObject also have several siblings to performSelector that are asynchronies. Most notably:
  • performSelector:withObject:afterDelay: - To execute the method on the current thread after a delay.
  • performSelectorInBackground:withObject: - To execute the method on a new background thread.
  • performSelectorOnMainThread:withObject:waitUntilDone: - To execute the method on the main thread.
  • performSelector:onThread:withObject:waitUntilDone: - To execute the method on any thread.
The asynchronous performers all depend on a NSRunLoop to function. This is not something you need to worry about unless you spawn a thread yourself. If you do then you need to also run the new threads run loop. Just skip that for now.