声音停止播放后如何执行 segue
How do I perform segue AFTER the sound has stopped playing
我在 Main.Storyboard 中制作了一个自定义 LaunchScreen,使声音看起来实际上是从 LaunchScreen 发出的。声音效果很好,也可以转至下一个视图控制器。唯一的问题是 segue 发生在声音停止播放之前。我希望在进行 segue 之前完成声音。从逻辑上讲,它应该可以工作,因为 performSegue 直接在 .play() 之后。但似乎两者同时发生。这是我的代码:
super.viewDidLoad()
//PLAY SOUND CLIP//
let musicFile = Bundle.main.path(forResource: "fanfare", ofType: ".mp3")
do {
try musicSound = AVAudioPlayer(contentsOf: URL (fileURLWithPath: musicFile!))
} catch { print("ERROR PLAYING MUSIC")}
musicSound.play() //WORKS
//
DispatchQueue.main.async() {
self.performSegue(withIdentifier: "myLaunchSegue", sender: self) //WORKS
}
我尝试添加:
perform(Selector(("showNavController")), with: self, afterDelay: 3)
其中 "showNavController" 只是 segue:
func showNavController() {
performSegue(withIdentifier: "myLaunchSegue", sender: nil)
}
但程序崩溃并出现错误 "uncaught exception.... ....unrecognized selector sent to instance"
我还尝试添加一个布尔值来阻止程序在声音播放之前继续运行,但没有成功。有什么想法吗?
/////////////////////////
更新:
尝试 Russels 的回答,但有几个问题。将 AVAudioPlayer 设置为委托,是否意味着将它设置在 class 旁边,如下所示:
class MyLaunchViewController: UIViewController, AVAudioPlayer { ...
另外,如何调用函数audioPlayerDidFinishPlaying?像这样:
audioPlayerDidFinishPlaying(musicSound, successfully: true)
我会 post 整个代码块。更容易理解...
import UIKit
导入 AVFoundation //FOR SOUND
class MyLaunchViewController: UIViewController, AVAudioPlayer {
var musicSound: AVAudioPlayer = AVAudioPlayer() //FOR SOUND
override func viewDidLoad() {
super.viewDidLoad()
//PLAY SOUND CLIP//
let musicFile = Bundle.main.path(forResource: "fanfare", ofType: ".mp3")
do {
try musicSound = AVAudioPlayer(contentsOf: URL (fileURLWithPath: musicFile!))
} catch { print("ERROR PLAYING MUSIC")}
musicSound.play() //WORKS
//
audioPlayerDidFinishPlaying(musicSound, successfully: true)
}
optional func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
DispatchQueue.main.async() {
self.performSegue(withIdentifier: "myLaunchSegue", sender: self)
}
}
我在 class 中编写 AVAudioPlayer 时出错(也许我误解了我应该做什么?)。它说我有多重继承。此外,它不希望我将新功能设置为可选功能,因为它仅适用于协议成员。最后,如果我更正错误和 运行 程序,下一个 segue 运行s 在声音播放完之前... :( sad panda.
您需要将 LaunchScreen 设为 AVAudioPlayerDelegate
,然后使用 audioPlayerDidFinishPlaying
回调。这就是您在第一个控制器中所需要的一切
import UIKit
import AVFoundation
class ViewController: UIViewController, AVAudioPlayerDelegate
{
var musicSound: AVAudioPlayer?
override func viewDidLoad() {
super.viewDidLoad()
//PLAY SOUND CLIP//
let musicFile = Bundle.main.path(forResource: "sound", ofType: ".wav")
do {
try musicSound = AVAudioPlayer(contentsOf: URL (fileURLWithPath: musicFile!))
} catch { print("ERROR PLAYING MUSIC")}
musicSound?.delegate = self
musicSound!.play() //WORKS
print("Next line after play")
}
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
DispatchQueue.main.async() {
print("audioPlayerDidFinishPlaying")
self.performSegue(withIdentifier: "myLaunchSegue", sender: self)
}
}
}
您可以在此处获取更多详细信息https://developer.apple.com/documentation/avfoundation/avaudioplayerdelegate/1389160-audioplayerdidfinishplaying
我在 Main.Storyboard 中制作了一个自定义 LaunchScreen,使声音看起来实际上是从 LaunchScreen 发出的。声音效果很好,也可以转至下一个视图控制器。唯一的问题是 segue 发生在声音停止播放之前。我希望在进行 segue 之前完成声音。从逻辑上讲,它应该可以工作,因为 performSegue 直接在 .play() 之后。但似乎两者同时发生。这是我的代码:
super.viewDidLoad()
//PLAY SOUND CLIP//
let musicFile = Bundle.main.path(forResource: "fanfare", ofType: ".mp3")
do {
try musicSound = AVAudioPlayer(contentsOf: URL (fileURLWithPath: musicFile!))
} catch { print("ERROR PLAYING MUSIC")}
musicSound.play() //WORKS
//
DispatchQueue.main.async() {
self.performSegue(withIdentifier: "myLaunchSegue", sender: self) //WORKS
}
我尝试添加:
perform(Selector(("showNavController")), with: self, afterDelay: 3)
其中 "showNavController" 只是 segue:
func showNavController() {
performSegue(withIdentifier: "myLaunchSegue", sender: nil)
}
但程序崩溃并出现错误 "uncaught exception.... ....unrecognized selector sent to instance"
我还尝试添加一个布尔值来阻止程序在声音播放之前继续运行,但没有成功。有什么想法吗?
///////////////////////// 更新: 尝试 Russels 的回答,但有几个问题。将 AVAudioPlayer 设置为委托,是否意味着将它设置在 class 旁边,如下所示:
class MyLaunchViewController: UIViewController, AVAudioPlayer { ...
另外,如何调用函数audioPlayerDidFinishPlaying?像这样:
audioPlayerDidFinishPlaying(musicSound, successfully: true)
我会 post 整个代码块。更容易理解...
import UIKit
导入 AVFoundation //FOR SOUND
class MyLaunchViewController: UIViewController, AVAudioPlayer { var musicSound: AVAudioPlayer = AVAudioPlayer() //FOR SOUND
override func viewDidLoad() {
super.viewDidLoad()
//PLAY SOUND CLIP//
let musicFile = Bundle.main.path(forResource: "fanfare", ofType: ".mp3")
do {
try musicSound = AVAudioPlayer(contentsOf: URL (fileURLWithPath: musicFile!))
} catch { print("ERROR PLAYING MUSIC")}
musicSound.play() //WORKS
//
audioPlayerDidFinishPlaying(musicSound, successfully: true)
}
optional func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
DispatchQueue.main.async() {
self.performSegue(withIdentifier: "myLaunchSegue", sender: self)
}
}
我在 class 中编写 AVAudioPlayer 时出错(也许我误解了我应该做什么?)。它说我有多重继承。此外,它不希望我将新功能设置为可选功能,因为它仅适用于协议成员。最后,如果我更正错误和 运行 程序,下一个 segue 运行s 在声音播放完之前... :( sad panda.
您需要将 LaunchScreen 设为 AVAudioPlayerDelegate
,然后使用 audioPlayerDidFinishPlaying
回调。这就是您在第一个控制器中所需要的一切
import UIKit
import AVFoundation
class ViewController: UIViewController, AVAudioPlayerDelegate
{
var musicSound: AVAudioPlayer?
override func viewDidLoad() {
super.viewDidLoad()
//PLAY SOUND CLIP//
let musicFile = Bundle.main.path(forResource: "sound", ofType: ".wav")
do {
try musicSound = AVAudioPlayer(contentsOf: URL (fileURLWithPath: musicFile!))
} catch { print("ERROR PLAYING MUSIC")}
musicSound?.delegate = self
musicSound!.play() //WORKS
print("Next line after play")
}
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
DispatchQueue.main.async() {
print("audioPlayerDidFinishPlaying")
self.performSegue(withIdentifier: "myLaunchSegue", sender: self)
}
}
}
您可以在此处获取更多详细信息https://developer.apple.com/documentation/avfoundation/avaudioplayerdelegate/1389160-audioplayerdidfinishplaying