Swift - AVAudioPlayer,声音播放不正确
Swift - AVAudioPlayer, sound doesn't play correctly
因为在应用程序处于活动状态时未显示 UILocalNotification
,我正在尝试配置一个 UIAlertController
并在它出现时播放一点声音。
我没问题,在 AppDelegate
中处理 notification/create 警报。我的问题与声音有关。确实,播放不正确
这是我目前的情况:
//...
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()
它只播放不到一秒钟。就像它突然被释放一样(?)。
我尝试了以下两件事:
- 将
AVAudioPlayer
状态切换回非活动状态:AVAudioSession.sharedInstance().setActive(false, error: nil)
就在警报创建之前(或显示警报之后)。如果我这样做,声音就会正确播放。但是,此方法是同步(阻塞)操作,因此它会延迟其他事情(声音后显示警报)。显然不是一个好的解决方案。
- 将 audioPlayer 属性 (
var audioPlayer = AVAudioPlayer()
) 移动到 class 级别,就在 window (var window: UIWindow?
) 下面。如果我这样做,声音会正确播放,警报也会正确显示。
我不明白为什么会这样。我错过了什么吗?这是解决我问题的正确方法吗?
在此先感谢所有可以帮助我的人understand/fixing。
您已经为您的问题提供了正确的解决方案,那就是#2;拥有 class 级 audioPlayer
属性。为什么会这样?
好吧,那是因为在代码中您设置了播放器、开始播放、显示弹出窗口,并且在完成所有操作后,该方法退出了它的作用域。自动内存管理 (ARC) 工作,以便在您退出该变量的范围时释放任何局部变量。如果您认为声音播放是异步的(例如,它会在不阻塞主线程的情况下播放),您可以在音频播放器播放完声音之前退出作用域。 ARC 注意到 audioPlayer
是一个局部变量并在此时释放它,但声音还没有播放完。
希望我说得够清楚了,如果还不明白可以再问!
因为在应用程序处于活动状态时未显示 UILocalNotification
,我正在尝试配置一个 UIAlertController
并在它出现时播放一点声音。
我没问题,在 AppDelegate
中处理 notification/create 警报。我的问题与声音有关。确实,播放不正确
这是我目前的情况:
//...
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()
它只播放不到一秒钟。就像它突然被释放一样(?)。
我尝试了以下两件事:
- 将
AVAudioPlayer
状态切换回非活动状态:AVAudioSession.sharedInstance().setActive(false, error: nil)
就在警报创建之前(或显示警报之后)。如果我这样做,声音就会正确播放。但是,此方法是同步(阻塞)操作,因此它会延迟其他事情(声音后显示警报)。显然不是一个好的解决方案。 - 将 audioPlayer 属性 (
var audioPlayer = AVAudioPlayer()
) 移动到 class 级别,就在 window (var window: UIWindow?
) 下面。如果我这样做,声音会正确播放,警报也会正确显示。
我不明白为什么会这样。我错过了什么吗?这是解决我问题的正确方法吗?
在此先感谢所有可以帮助我的人understand/fixing。
您已经为您的问题提供了正确的解决方案,那就是#2;拥有 class 级 audioPlayer
属性。为什么会这样?
好吧,那是因为在代码中您设置了播放器、开始播放、显示弹出窗口,并且在完成所有操作后,该方法退出了它的作用域。自动内存管理 (ARC) 工作,以便在您退出该变量的范围时释放任何局部变量。如果您认为声音播放是异步的(例如,它会在不阻塞主线程的情况下播放),您可以在音频播放器播放完声音之前退出作用域。 ARC 注意到 audioPlayer
是一个局部变量并在此时释放它,但声音还没有播放完。
希望我说得够清楚了,如果还不明白可以再问!