2016-09-11 6 views
0

ユーザーにボタンを押して、背景色を変えて(黄色に)、WAVを再生し、WAVの完了時にボタンを元の色に戻す)。したがって、サウンドの周りに補完ハンドラがあります。以下のコードをさまざまに組み合わせてみましたが、WAVが再生され、ボタンが色を変えるように見えません。スウィフト - 押しボタン(完了ハンドラーの問題)

これは間違ったアプローチですか、何か間違っていますか?補完ハンドラを色の変化の周りに置く必要はないと思いますが、残念です。

多くのありがとうございます。

typealias CompletionHandler = (success:Bool) -> Void 

@IBAction func fireButton(sender: AnyObject) { 
    playLaser({ (success)-> Void in 
     if success { 
      self.shots -= 1 
      self.labelShotsLeft.text = String(self.shots) 
     } else { 

     } 
    }) 
} 

func playLaser(completionHandler: CompletionHandler) { 
    fireButton.layer.backgroundColor = UIColor.yellowColor().CGColor 
    let url = NSBundle.mainBundle().URLForResource("laser", withExtension: "wav")! 
    do { 
     player = try AVAudioPlayer(contentsOfURL: url) 
     guard let player = player else { return } 
     player.prepareToPlay() 
     player.play() 
     } catch let error as NSError { 
      print(error.description) 
    } 
    self.fireButton.layer.backgroundColor = UIColor.redColor().CGColor 
    completionHandler(success: true) 
} 

答えて

0

これはもう少しでこれらの質問の一つであります目を満たすよりも微妙です。私は各タスクの周りに3つの完了ハンドラーを置いてみました:色を黄色に変え、音を出し、色を赤に戻してください。コードは、私がNSLoggedとして正しいシーケンスで実行されていましたが、ボタンは画面更新コントロールのために色が変わっていませんでした。ここで私は他の読者が役に立つかもしれません期待していること動作するコードは次のとおりです。

スウィフト2.0

@IBAction func fireButton(sender: AnyObject) { 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { 
     dispatch_sync(dispatch_get_main_queue()) { 
      self.fireButton.layer.backgroundColor = UIColor.yellowColor().CGColor 
     } 
     self.playLaser({ (success)-> Void in 
      if success { 
       self.shots -= 1 
      } else { 
      } 
     }) 
     dispatch_sync(dispatch_get_main_queue()) { 
      self.labelShotsLeft.text = String(self.shots) 
      self.fireButton.layer.backgroundColor = UIColor.redColor().CGColor 
     } 
    } 
} 

func playLaser(completion: (success: Bool) ->()) { 
    let url = NSBundle.mainBundle().URLForResource("laser", withExtension: "wav")! 
    do { 
     player = try AVAudioPlayer(contentsOfURL: url) 
     guard let player = player else { return } 
     player.play() 
     completion(success: true) 
     } catch let error as NSError { 
     completion(success: false) 
    } 
} 

スウィフト3.0

@IBAction func fireButton(_ sender: AnyObject) { 
    let fireQueue = DispatchQueue(label: "queueFirebutton") 
    fireQueue.async { 
     DispatchQueue.main.sync { 
      self.fireButtonDisabled() 
     } 
     DispatchQueue.main.sync { 
      self.playLaser() 
      self.shots -= 1 
      if self.shots <= 0 { 
       self.shots = 0 
      } 
     } 
     DispatchQueue.main.sync { 
      if self.shots < 0 { self.shots = 0} 
      self.labelShotsLeft.text = String(self.shots) 
      sleep(1) 
      self.fireButtonEnabled() 
     } 
    } 
} 

func playLaser() { 
    let url = Bundle.main.url(forResource: "laser", withExtension: "wav")! 
    do { 
     player = try AVAudioPlayer(contentsOf: url) 
     guard let player = player else { return } 
     player.play() 
    } catch { 
    } 
} 
0

play.play()と言うだけで、コードは魔法のように一時停止して待機しません。恐ろしいことです。したがって、いわゆる完了ハンドラは完了ハンドラではありません。 すぐにを実行します - つまり、すぐに開始再生します。あなたのコードは、オーディオプレーヤーがが終了したときの情報を取得することについて何もしません。が再生されます。

そのためには、デリゲートを設定し、オーディオプレーヤーが再生を終了すると出力するdelegate messageを受け取る必要があります。

1

AVAudioPlayerを検出するには、AVAudioPlayerDelegateを使用する必要があります。

あなたはこのような何か書く必要がある場合があります。

func playLaser(completionHandler: CompletionHandler) { 
    fireButton.layer.backgroundColor = UIColor.yellowColor().CGColor 
    let url = NSBundle.mainBundle().URLForResource("laser", withExtension: "wav")! 
    do { 
     player = try AVAudioPlayer(contentsOfURL: url) 
     guard let player = player else { return } 
     player.delegate = self //<- Sorry, this was missing in my first post 
     player.play() 
    } catch let error as NSError { 
     print(error.description) 
    } 
    audioPlayerCompletionHandler = completionHandler 
} 

var audioPlayerCompletionHandler: CompletionHandler? 
func audioPlayerDidFinishPlaying(player: AVAudioPlayer, successfully flag: Bool) { 
    self.fireButton.layer.backgroundColor = UIColor.redColor().CGColor 
    audioPlayerCompletionHandler?(success: true) 
} 

を(あなたのViewControllerの宣言ヘッダーにAVAudioPlayerDelegateへの適合性を追加する必要があります。)

関連する問題