简体   繁体   中英

Control flow in Objective-C

I am working through Beginning iPhone Development . In the book is this method:

-(void)playWinSound
{
    NSString *path = [[NSBundle mainBundle] pathForResource:@"win" ofType:@"wav"];
    SystemSoundID soundID;
    AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:path], &soundID);
    AudioServicesPlaySystemSound (soundID);     
    winLabel.text = @"WIN!";
    [self performSelector:@selector(showButton) withObject:nil afterDelay:1.5];
}

-(IBAction)spin{
    BOOL win = NO;
    int numInRow = 1;
    int lastVal = -1;
    for (int i = 0; i < 5; i++)
    {
        int newValue = random() % [self.column1 count];

        if (newValue == lastVal)
            numInRow++;
        else
            numInRow = 1;

        lastVal = newValue;
        [picker selectRow:newValue inComponent:i animated:YES];
        [picker reloadComponent:i];
        if (numInRow >= 3)
            win = YES;
    }

    button.hidden = YES;
    NSString *path = [[NSBundle mainBundle] pathForResource:@"crunch" ofType:@"wav"];
    SystemSoundID soundID;
    AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:path], &soundID);
    AudioServicesPlaySystemSound (soundID);

    if (win)
        [self performSelector:@selector(playWinSound) withObject:nil afterDelay:.5];
    else
        [self performSelector:@selector(showButton) withObject:nil afterDelay:.5];

    winLabel.text = @"";
}

When you click the spin button it calls this spin method. If the win is YES, playWinSound is called which changes the value of winLabel to @"Win!". Why is it that if spin results in a win, the text in winLabel changes to @"Win!" and stays that way. Shouldn't the flow return to the spin method which will change winLabel to @""?

Yes, and the flow does return to the spin method. The trick is in the call which is performing the playWinSound method:

[self performSelector:@selector(playWinSound) withObject:nil afterDelay:.5];

Note the afterDelay portion of the method. This schedules an invocation of playWinSound at the first available time after 0.5 seconds have passed. Specifically, the invocation will take place at the beginning of the first run loop after 0.5 seconds have passed. This method is being called inside an already-running run loop, so the playWinSound cannot possibly execute until after the spin method has returned.

That said, this seems a very odd way to structure the program. I assume they're setting winLabel.text to @"" to make sure that it gets reset back to an empty string unless it's specifically going to become @"Win!" , but I would have structured it very differently. Nevertheless, that's why it works.

[self performSelector:@selector(playWinSound) withObject:nil afterDelay:.5];

This method queues the action, returns right away and resets the text to "". If it actually waited and then called selector after timeout it would waste resources.

The action is then executed after the timeout and will set the text to "WIN".

Apple reference :

This method sets up a timer to perform the aSelector message on the current thread's run loop ...

我认为发生的事情是通过调用performSelector方法,它得到了afterDelay周期...所以方法排队,winLabel.text = @“”代码执行,然后playWinSound方法触发,再次更改标签。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM