2016-09-11 3 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

Это один из тех вопросов, которые немного больше тонкий, чем кажется на первый взгляд. Я попытался поместить три обработчика завершения вокруг каждой задачи: изменить цвет на желтый, воспроизвести звук, изменить цвет обратно на красный. Код выполнялся в правильной последовательности, так как я NSLogged, но кнопка никогда не меняла цвет из-за элементов управления обновлением экрана. Вот код, который работает, что я надеюсь, что другие читатели могут оказаться полезными:

Swift 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) 
    } 
} 

Swift 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.

Вам может понадобиться, чтобы написать что-то вроде этого: (. Вы должны добавить соответствие с AVAudioPlayerDelegate в заголовке декларации вашего ViewController в)

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) 
} 

Смежные вопросы