简体   繁体   中英

AVAudioPlayer not playing sound

I have a WatchKit app that when a button is tapped on the watch it signals the iOS app to play a sound. For some reason, the sound isn't playing when I use a custom class to handle setting up an instance of AVAudioPlayer and playing the sound. If I do that part within session:didReceiveMessage:replyHandler: it plays fine.

Here is the custom class:

import AVFoundation

class ChildClass {
    let mySound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("test", ofType: "wav")!)
    var audioPlayer: AVAudioPlayer!

    func playSound() {
        do {
            print("Playing sound")
            self.audioPlayer = try AVAudioPlayer(contentsOfURL: mySound)
            self.audioPlayer.play()
        } catch {
            print("Error getting audio file")
        }
    }
}

Which is instantiated in my ViewController :

class ViewController: UIViewController, WCSessionDelegate {
    var session: WCSession!

    override func viewDidLoad() {
        super.viewDidLoad()

        if WCSession.isSupported() {
            session = WCSession.defaultSession()
            session.delegate = self
            session.activateSession()
        }
    }

    func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {
        let mySounds = ChildClass()
        mySounds.playSound()
    }
}

Setting up breakpoints in ChildClass.playSound() I can confirm that it is getting called. But not only doesn't the sound play but the print() doesn't appear to print anything to the console either.

Is there something about the AVAudioPlayer instance being in a custom class causing it to not play the sound? Or, perhaps the audio isn't being played by the iOS app for some reason?

Your "mySounds" goes out of scope before the sound can play. Make it an instance variable and see what happens.

func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {
    let mySounds = ChildClass()
    mySounds.playSound()
}

is not being called. I tried putting the code inside

if WCSession.isSupported() {
        session = WCSession.defaultSession()
        session.delegate = self
        session.activateSession()

        let mySounds = ChildClass()
        mySounds.playSound()
    }

and it works just fine.

WatchConnectivity methods are called very early in the app life cycle. It is recommended that you set them up in the AppDelegate or ExtensionDelegate. Otherwise the methods will get called before your delegate is setup and you will likely miss them.

In iOS, this should be called in application:didFinishLaunchingWithOptions. In watchOS, this should be in the init method of your ExtensionDelegate. The reason for it being in the init method on the watch extension is because the applicationDidFinishLaunching method is not called if you launch a complication, but the init method is called for both the complication and the watch extension.

If you need to send data to a UIViewController like in your case, you an use NSNotificationCenter to notify the controller. Also, remember watch connectivity methods are all called on a background thread in case you try to update any UI.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM