我希望用户按下按钮,它会改变背景颜色(变为黄色),播放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 :(得分:2)
要检测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)
}
(您需要将AVAudioPlayerDelegate
的一致性添加到ViewController的声明标题中。)
答案 1 :(得分:1)
代码不会因为你说play.play()
而神奇地暂停和等待 - 这太可怕了!因此,您所谓的完成处理程序根本不是完成处理程序。它会立即运行 - 也就是说,只要你开始播放。您的代码不会获取有关音频播放器何时完成播放
为此,您需要配置一个委托并接收音频播放器完成播放时发出的delegate message。
答案 2 :(得分: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 {
}
}