Swift-AVAudioPlayer,声音无法正常播放 [英] Swift - AVAudioPlayer, sound doesn't play correctly

查看:152
本文介绍了Swift-AVAudioPlayer,声音无法正常播放的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因为在应用程序处于活动状态时未显示UILocalNotification,所以我正在尝试配置UIAlertController并在出现时播放一些声音.

Because UILocalNotification is not being displayed while the application is in active stat, I'm trying to configure an UIAlertController and playing a little sound when it appears.

AppDelegate中,我没问题来处理通知/创建警报.我的问题与声音有关.确实,它无法正常播放.

I've no problem, in the AppDelegate, to handle the notification/create the alert. My problem concerns the sound. Indeed, it doesn't play correctly.

这是我到目前为止所拥有的:

Here is what I have so far :

//...
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() 它只播放不到一秒钟.就像是突然被释放一样(?).

With that, when the player go through this line : audioPlayer.play() It only play for less then a second. Like if it was suddently deallocated maybe (?).

我尝试了以下两件事:

  1. AVAudioPlayer状态切换回非活动状态:AVAudioSession.sharedInstance().setActive(false, error: nil)就在警报创建之前(或在显示警报之后).如果这样做,声音将正确播放.但是,此方法是同步(阻止)操作,因此会延迟其他操作(在声音后显示提示).显然不是一个好的解决方案.
  2. 将audioPlayer属性(var audioPlayer = AVAudioPlayer())移动到类级别,就在窗口(var window: UIWindow?)下方.如果这样做,声音会正确播放,并且警报也会正确显示.
  1. Switching back the AVAudioPlayer status to inactive: AVAudioSession.sharedInstance().setActive(false, error: nil) just before the alert creation (or just after showing it). If I do that, the sound is played correctly. But, this method is a synchronous (blocking) operation, so it delays other thing (alert being shown after the sound). Apparently not a good solution.
  2. Move the audioPlayer property (var audioPlayer = AVAudioPlayer()) to the class level, just under the window (var window: UIWindow?). If I do that, the sound is played correctly and the alert is shown correctly too.

我不明白为什么它会那样工作.我想念什么吗?是解决我的问题的正确方法吗?

I don't understand why it works like that. Am I missing something? Is it the proper way to solve my problem?

在此先感谢所有可以帮助我了解/解决此问题的人.

Thanks in advance to everyone who could help me understand/fixing this.

推荐答案

您已经提供了解决问题的正确方法,那就是#2;具有类级别的audioPlayer属性.为什么会这样呢? 好吧,这是因为在代码中设置了播放器,开始播放,显示弹出窗口,并且在完成所有操作后,该方法退出了作用域.自动内存管理(ARC)起作用,以便在退出该变量的范围时释放所有局部变量.如果您认为声音播放是异步的(例如,它将在不阻塞主线程的情况下播放),请在音频播放器完成播放声音之前退出示波器. ARC注意到audioPlayer是局部变量,并在那时将其释放,但是声音尚未播放完毕.

You already provided the correct solution to your problem and that would be #2; to have a class-level audioPlayer property. Why is this so? Well, that's because in the code you setup the player, start the playback, show the pop-up and after everything is done, the method exits its scope. The automated memory management (ARC) works so that any local variables get released when you exit the scope of that variable. If you consider that sound playback is asynchronous (eg. it will play without blocking the main thread), you exit the scope before the audio player is finished playing the sound. ARC notices that audioPlayer is a local variable and releases it at that point, but the sound is not done playing yet.

我希望我足够清楚,如果不能随意问更多的话!

I hope I was clear enough, if not feel free to ask more!

这篇关于Swift-AVAudioPlayer,声音无法正常播放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆