Laurence Wingo
Laurence Wingo

Reputation: 3952

Initializing AVAudioPlayer to be used in more than one function

Usual AVAudioPlayer tutorials online creates a AVAudioPlayer within a function to where the play and stop functions of the AVAudioPlayer object aren't available to the object directly from other functions. The problem is that I would like another function to stop the sound from the AVAudioPlayer. This seems pretty simple by initializing the objects at the top of the class in hopes it would be accessible however in Swift3 the init function for AVAudioPlayer includes a throw and a parameter for the sound file. Swift doesn't allow us to use an instance member within a property initializer so I'm stuck on my thought process of how this could be written.

The only error I'm running into at this point is not being allowed to use an instance member in the property initializer when creating "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.
    }

}

Upvotes: 1

Views: 293

Answers (1)

Adeel Miraj
Adeel Miraj

Reputation: 2496

You need to use Lazy initialisation/instantiation for that. In your case this is all you need to do.

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

}()

For more about Lazy Initialisation this is a good read. The interesting thing in your case is that the initialiser throws. I think this forum discussion is helpful to have a slight idea.

Upvotes: 1

Related Questions