1

I have a method that takes several params, I need to delay a portion of that method. I DO NOT want to split it into several methods and use [self performSelectorAfterDelay] because the delay requires params already in that method. I need something like the following

-(void)someMethod{
.....

delay {

     more code but not a separate self method
}
... finish method
}
Eric
  • 4,063
  • 2
  • 27
  • 49

2 Answers2

3

The dispatch_after function seems to line up with what you need:

double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
    // this code is going to be executed, on the main queue (or thread) after 2.0 seconds.
});

Of course, the time is configureable, and it's a bit confusing to read at first, but once you get used to how blocks work in conjunction with objective-c code, you should be good to go.

One word of caution:

NEVER, NEVER, NEVER! Block the main thread of an iPhone app using sleep(). Just don't do it!

Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201
1

Looks like an overkill.

-(void)someMethod{

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
        NSLog(@"Start code");
        dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
        dispatch_sync(backgroundQueue, ^{

            sleep(5);
            // delayed code
            NSLog(@"Delayed code");
        });

        dispatch_sync(backgroundQueue, ^{

            // finishing code
            NSLog(@"Finishing code");
        });
    });

}

backgroundQueue might be user at external dispatch call. It looks really bad though :)

A-Live
  • 8,904
  • 2
  • 39
  • 74
  • This isn't the right way to do it. GCD has built in support for delays, and trying to go off to another queue and block it just so you can return to the main queue doesn't seem to make sense. Another note - this will actually deadlock. `dispatch_get_global_queue` will return the same queue if it can, so using `sync` on that queue will deadlock the app, for certain. Read more here: http://stackoverflow.com/questions/10984732/gcd-why-cant-we-use-a-dispatch-sync-on-the-current-queue – Richard J. Ross III Oct 29 '12 at 16:46
  • @Richard J. Ross III I wonder, where did you see the requirement to return to the main queue ? The calling queue might be at background, isn't it ? – A-Live Oct 29 '12 at 16:48
  • Let me make it a separate comment, I've jsut tried to do the following snippet with the same queue: `dispatch_async(backgroundQueue, ^{ dispatch_sync(backgroundQueue, ^{sleep(10); }); dispatch_sync(backgroundQueue, ^{ }); });` - No deadlock, what would you say ? – A-Live Oct 29 '12 at 16:50
  • true, but I know that most applications never actually leave the main queue, and regardless, returning to the main queue is the most logical solution, so you can properly edit UI controls & such (in the case of a timer, as it appears the OP is doing). – Richard J. Ross III Oct 29 '12 at 16:51
  • Also, wouldn't you agree that dispatch_after is a much more succinct and built-in way of doing this? There's no possibility of a deadlock, it's cleaner & shorter than you example, too. – Richard J. Ross III Oct 29 '12 at 16:52
  • dispatch_after is absolutely a better way to solve the requested problem, there's no doubt. – A-Live Oct 29 '12 at 16:54