7

I'm working on an iPad project that uses a third-party SDK, and have been reading through the SDK code to learn about it and objective-c. I came across the following line in an asynchronous callback:

[self performSelector:@selector(doSomething) withObject:nil afterDelay:0];

I've read through the documentation on that selector. The relevant line appears to be the following:

Specifying a delay of 0 does not necessarily cause the selector to be performed immediately. The selector is still queued on the thread’s run loop and performed as soon as possible.

I can't determine why one should write [self performSelector:@selector(doSomething) withObject:nil afterDelay:0], as opposed to merely writing [self doSomething]. It seems to me that a delay of zero means that the call should be made immediately. Clearly I'm missing something, it's unlikely that the framework author chose this approach at random. Other StackOverflow answers don't shed any light on this either. Is the "performSelector" selector being used because the doSomething selector itself is asynchronous, and the call is being made in an asynchronous callback?

I did find another link suggesting the following:

It's interesting to note that using performSelector with afterDelay will also let the warning [viz, a compiler warning] go away: ...

[self performSelector:aSelector withObject:nil afterDelay:0.0];

So did the author use this code to suppress a compiler warning only? If that's the case, then it's probably preferable to suppress the warnings through clang push/pops, as suggested in this thread.

If anyone has a cogent explanation as to why the author used the ...afterDelay method, I'd be grateful. Thanks.

Edit Oct 22, 2012: I don't believe that the sole answer given here by @rmaddy is wholly applicable to my situation, but it's still a good answer, so I'll accept it. I'll keep tabs on this question and come back if I find anything new. Thanks. J.Z.

Community
  • 1
  • 1
J.Z.
  • 882
  • 9
  • 13
  • Can you point us to the framework? It might help in giving the context. – drekka Oct 19 '12 at 03:52
  • @drekka: It's the [Salesforce IOS SDK](https://github.com/forcedotcom/SalesforceMobileSDK-iOS). The question was about a line in /native/SalesforceSDK/SalesforceSDK/Classes/NativeApp/SFNativeRestAppDelegate.m. – J.Z. Oct 19 '12 at 11:44

1 Answers1

6

One possible use of something like:

[self performSelector:@selector(doSomething) withObject:nil afterDelay:0];

is to allow the current runloop to complete before 'doSomething' is called. In other words, the current call stack can be completed (the current method returns) before 'doSomething' is called. Often this is used to give the UI a chance to update.

It's hard to know the author's true intent though without more context but this is a common use.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • 1
    Correct, but to nit-pick: Not the call stack; emphasis on current pass through run loop which might be quite complex (go read the docs on all the phases of CFRunLoop). In general, this pattern is to be avoided (though it is sometimes necessary) because it tends to be fragile and yields quite a bit of fun when one after-delay-0 triggers another after-delay-0 triggers yet another after-delay-0, etc.... – bbum Oct 19 '12 at 07:19
  • @rmaddy: I see. In this case it doesn't appear to be applicable. The call is made in an asynchronous callback during an OAuth 2.0 cycle (the OAuth stuff isn't germane to the question), so the concept of "current run loop" may not be as applicable. – J.Z. Oct 19 '12 at 11:54
  • @bbum I knew when I wrote "call stack" that it wasn't really the right term. Thanks for clarifying. – rmaddy Oct 19 '12 at 14:21