Question

I'm trying to initiate a delay in my code so that when the action gets to that part of the code, everything stops, for as long as the delay is scheduled. I already have setup the time delay, it's just a matter of how the code is supposed to execute.

This is the time delay that I've employed in my project:

NSDate *timeDelay = [NSDate dateWithTimeIntervalSinceNow:5];
[NSThread sleepUntilDate:timeDelay];

As you can see, this snippet inputs a 5 second delay. The problem I'm having, is that when I employ this code it doesn't do what I would expect it to do. Below is the function I'm trying to run:

- (IBAction)executeProgram
{
    UIAlertView *delayAlert = [[UIAlertView alloc]
                                initWithTitle:@"Delay"
                                message:@"This message follows with a 5 second delay."
                                delegate:nil
                                cancelButtonTitle:nil
                                otherButtonTitles:nil, nil];

    // Enable when time is working properly
    [delayAlert show];

    NSDate *timeDelay = [NSDate dateWithTimeIntervalSinceNow:5];
    [NSThread sleepUntilDate:timeDelay];

    // dismisses the alert
    [delayAlert dismissWithClickedButtonIndex:0 animated:YES];
}

I would expect this code to first, display the alert, wait 5 seconds, and then dismiss the alert. However, that doesn't happen. Instead what happens, is that when I click on the button, there is a five second delay first, then the alert pops up and almost instantaneously dismisses itself. I've tried this with another snippet of code for the time delay, with the same reaction.

CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();

for (int x = 0; x<=5000; x++)
{
    NSLog(@"%i",x);
}

CFAbsoluteTime endTime = CFAbsoluteTimeGetCurrent();
CFAbsoluteTime elapsedTime = endTime - startTime;

What am I doing wrong here? Why would the delay execute before the alert pops up?

Was it helpful?

Solution

That's because you're sleeping (and blocking) the thread that the alert should be presented from (the main/UI thread). I recommend you use dispatch_after to sleep asynchronously, and then call back to the main thread after the 5 seconds has passed to dismiss the alert. Something like this:

UIAlertView *delayAlert = [[UIAlertView alloc]
                            initWithTitle:@"Delay"
                            message:@"This message follows with a 5 second delay."
                            delegate:nil
                            cancelButtonTitle:nil
                            otherButtonTitles:nil, nil];

[delayAlert show];

double delayInSeconds = 5.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    [delayAlert dismissWithClickedButtonIndex:0 animated:YES];
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top