Swift - 按下按钮(完成处理程序问题)
Swift - Press Button (completion handler issue)
我希望用户按下一个按钮,它会改变背景颜色(黄色),播放 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)
}
代码不会因为你说 play.play()
就神奇地暂停和等待——那太可怕了!因此,您所谓的完成处理程序根本不是完成处理程序。它会立即运行——也就是说,一旦你开始播放。您的代码对获取有关音频播放器何时 完成 播放的信息没有任何作用。
为此,您需要配置一个委托并接收音频播放器在播放结束时发出的 delegate message。
要检测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 的声明 header。)
这是一个比看上去更微妙的问题。我尝试在每个任务周围放置三个完成处理程序:将颜色更改为黄色、播放声音、将颜色更改回红色。代码按照我 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 {
}
}
我希望用户按下一个按钮,它会改变背景颜色(黄色),播放 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)
}
代码不会因为你说 play.play()
就神奇地暂停和等待——那太可怕了!因此,您所谓的完成处理程序根本不是完成处理程序。它会立即运行——也就是说,一旦你开始播放。您的代码对获取有关音频播放器何时 完成 播放的信息没有任何作用。
为此,您需要配置一个委托并接收音频播放器在播放结束时发出的 delegate message。
要检测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 的声明 header。)
这是一个比看上去更微妙的问题。我尝试在每个任务周围放置三个完成处理程序:将颜色更改为黄色、播放声音、将颜色更改回红色。代码按照我 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 {
}
}