声音停止播放后如何执行 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