2009-06-25 19 views
1

私はBeginning iPhone Developmentで作業しています。本書では、この方法はObjective-Cの制御フロー

-(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 = @""; 
} 

です。スピンボタンをクリックすると、このスピンメソッドが呼び出されます。勝利がYESの場合、winLabelの値を@ "Win!"に変更するplayWinSoundが呼び出されます。スピンの結果が勝つと、winLabelのテキストが@ "Win!"に変わるのはなぜですか?そのようにとどまる。フローは、winLabelを@ ""に変更するスピンメソッドに戻るべきではありませんか?

答えて

3

はい、フローになります。スピンメソッドに戻ります。

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

注方法のafterDelay部分:トリックplayWinSound方法を実行しているコールです。これは、0.5秒が経過した後に最初に利用可能な時間にplayWinSoundの呼び出しをスケジュールします。具体的には、呼び出しは、0.5秒が経過した後の最初の実行ループの開始時に行われます。このメソッドはすでに実行中のループ内で呼び出されているため、playWinSoundspinメソッドが返されるまで実行されません。

つまり、これはプログラムを構成する非常に奇妙な方法のようです。私は彼らが@"Win!"になるつもりがない限り空の文字列にリセットされることを確認するためにwinLabel.text@""に設定していると仮定していますが、構造が非常に異なっています。それにもかかわらず、それはそれが機能する理由です。

0

私はperformSelectorメソッドを呼び出すことによって、そのafterDelay期間を得ていると思います...メソッドがキューに入れられ、winLabel.text = @ ""コードが実行され、その後playWinSoundメソッドが起動し、ラベルを再度変更します。

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

このメソッドはアクションをキューに入れ、すぐに戻り、テキストを ""にリセットします。実際に待ってからタイムアウト後にセレクタを呼び出すと、リソースが浪費されます。

アクションはタイムアウト後に実行され、テキストを「WIN」に設定します。

Apple reference

この方法は 現在 のスレッドの実行ループ上のaSelectorメッセージを実行するためにタイマーを設定します...