Swift - AVAudioPlayer,声音无法正常播放

时间:2015-01-12 22:39:27

标签: swift avaudioplayer uilocalnotification appdelegate uialertcontroller

由于在应用处于有效状态时未显示UILocalNotification,我尝试配置UIAlertController并在出现时播放一些声音。

我在AppDelegate中处理通知/创建提醒是没问题的。我的问题涉及声音。实际上,它没有正确发挥。

这是我到目前为止所做的:

//...
class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    // Override point for customization after application launch.

    // Notifications permissions
    let types: UIUserNotificationType = UIUserNotificationType.Sound | UIUserNotificationType.Alert
    let settings: UIUserNotificationSettings = UIUserNotificationSettings(forTypes: types, categories: nil)
    application.registerUserNotificationSettings(settings)

    return true
}

func application(application: UIApplication!, didReceiveLocalNotification notification: UILocalNotification!) {
    let state : UIApplicationState = application.applicationState
    var audioPlayer = AVAudioPlayer()

    if (state == UIApplicationState.Active) {
        // Create sound

        var error:NSError?
        var audioPlayer = AVAudioPlayer()

        AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient, error: nil)
        AVAudioSession.sharedInstance().setActive(true, error: nil)

        let soundURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("sound", ofType: "wav")!)

        audioPlayer = AVAudioPlayer(contentsOfURL: soundURL, error: &error)

        if (error != nil) {
            println("There was an error: \(error)")
        } else {
            audioPlayer.prepareToPlay()
            audioPlayer.play()
        }

        // Create alert
        let alertController = UIAlertController(title: "Alert title", message: "Alert message.", preferredStyle: .Alert)

        let noAction = UIAlertAction(title: "No", style: .Cancel) { (action) in
            // ...
        }
        let yesAction = UIAlertAction(title: "Yes", style: .Default) { (action) in
            // ...
        }

        alertController.addAction(noAction)
        alertController.addAction(yesAction)

        self.window?.rootViewController?.presentViewController(alertController, animated: true, completion: nil)

    }

}

这样,当玩家通过这一行时:audioPlayer.play() 它只播放不到一秒钟。就像它突然被解除分配一样(?)。

我尝试了以下两件事:

  1. 在创建警报之前(或在显示警报之后)将AVAudioPlayer状态切换回非活动状态:AVAudioSession.sharedInstance().setActive(false, error: nil)。如果我这样做,声音播放正确。但是,这种方法是一种同步(阻塞)操作,因此它会延迟其他事情(声音在声音后显示)。显然不是一个好的解决方案。
  2. 将audioPlayer属性(var audioPlayer = AVAudioPlayer())移动到窗口(var window: UIWindow?)下的类级别。如果我这样做,声音播放正确,警报也会正确显示。
  3. 我不明白为什么会这样。我错过了什么吗?这是解决我问题的正确方法吗?

    提前感谢所有能帮助我理解/解决此问题的人。

1 个答案:

答案 0 :(得分:3)

您已经为您的问题提供了正确的解决方案,那就是#2;拥有类级audioPlayer属性。为什么会这样? 嗯,那是因为在代码中你设置了播放器,开始播放,显示弹出窗口,一切都完成后,该方法退出其范围。自动内存管理(ARC)可以在退出该变量的范围时释放任何本地变量。如果您认为声音播放是异步的(例如,它将在不阻塞主线程的情况下播放),则在音频播放器播放完声音之前退出示波器。 ARC注意到audioPlayer是一个局部变量并在那时释放它,但声音还没有播放完毕。

我希望我很清楚,如果没有随意提出更多的问题!