初始化 AVAudioPlayer 以用于多个函数

Initializing AVAudioPlayer to be used in more than one function

通常的 AVAudioPlayer 在线教程会在一个函数内创建一个 AVAudioPlayerAVAudioPlayer 对象的播放和停止函数不能直接从其他函数使用。问题是我想要另一个函数来停止来自 AVAudioPlayer 的声音。这看起来很简单,通过初始化 class 顶部的对象,希望它可以访问,但是在 Swift3 中,AVAudioPlayerinit 函数包含一个 throw 和声音文件的参数。 Swift 不允许我们在 属性 初始化器中使用实例成员,所以我一直在思考如何编写它。

此时我 运行 遇到的唯一错误是在创建 "backgroundMusicPlayer":

时不允许在 属性 初始化程序中使用实例成员
import UIKit
import AVFoundation

class MadLibOneViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var thePlace: UITextField!
    @IBOutlet weak var theVerb: UITextField!
    @IBOutlet weak var theNumber: UITextField!
    @IBOutlet weak var theTemplate: UITextView!
    @IBOutlet weak var theStory: UITextView!
    @IBOutlet weak var generateStoryButton: UIButton!
    @IBOutlet weak var proceedToNextMadLib: UIButton!
    //var backgroundMusicPlayer = AVAudioPlayer()

    var error:NSError?

    var path = Bundle.main.path(forResource: "bensound-cute", ofType: "mp3")

    var url: NSURL {
        return NSURL(fileURLWithPath: path!)
    }

    var backgroundMusicPlayer: AVAudioPlayer = try AVAudioPlayer(contentsOf: url as URL, error: &error)





    @IBAction func createStory(_ sender: AnyObject) {
        theStory.text=theTemplate.text
    theStory.text=theStory.text.replacingOccurrences(of: "<place>", with: thePlace.text!)
        theStory.text=theStory.text.replacingOccurrences(of: "<verb>", with: theVerb.text!)
        theStory.text=theStory.text.replacingOccurrences(of: "<number>", with: theNumber.text!)

        generateStoryButton.isHidden=true
        proceedToNextMadLib.isHidden=false

    }

    @IBAction func showNextStory(_ sender: AnyObject) {

        view.backgroundColor=UIColor.green

        let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
        let resultViewController = storyBoard.instantiateViewController(withIdentifier: "MadLibTwoViewController") as! MadLibTwoViewController
        self.present(resultViewController, animated:true, completion:nil)

    }

    @IBAction func hideKeyboard(_ sender: AnyObject) {
        thePlace.resignFirstResponder()
        theVerb.resignFirstResponder()
        theNumber.resignFirstResponder()
        theTemplate.resignFirstResponder()
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        proceedToNextMadLib.isHidden=true
        view.backgroundColor = UIColor.purple


        // Do any additional setup after loading the view.
        self.theVerb.delegate = self
        self.thePlace.delegate = self
        self.theNumber.delegate = self

    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        self.view.endEditing(true)
        return false
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

为此您需要使用 Lazy initialisation/instantiation。在您的情况下,这就是您需要做的全部。

lazy var player: AVAudioPlayer = {
    [unowned self] in
    do {
        return try AVAudioPlayer.init(contentsOf: self.url)
    }
    catch {
        return AVAudioPlayer.init()
    }

}()

想了解更多Lazy Initialisationthis is a good read. The interesting thing in your case is that the initialiser throws. I think this forum discussion有一点想法很有帮助。