2

UILocalNotification이 응용 프로그램이 활성 상태 인 동안 표시되지 않기 때문에 UIAlertController을 구성하고 표시 될 때 약간의 소리를 재생하려고합니다.Swift - AVAudioPlayer 소리가 올바르게 재생되지 않습니다.

나는 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() 그것은 단지 두 번째 적은 다음으로 게임 여기

는 내가 지금까지 가지고있는 것입니다. 마치 suddently 할당 취소 어쩌면 (?). 비활성하기 위해 AVAudioPlayer 상태를 다시 전환

  1. : 그냥 경고 생성하기 전에 (또는 그것을 보여주는 후) AVAudioSession.sharedInstance().setActive(false, error: nil)

    나는 아래의 두 가지를 시도했다. 그렇게하면 소리가 제대로 재생됩니다. 그러나이 방법은 동기식 (차단) 작업이므로 다른 것을 지연시킵니다 (경고음이 소리 뒤에 표시됨). 분명히 좋은 해결책이 아닙니다.
  2. audioPlayer 속성 (var audioPlayer = AVAudioPlayer())을 창 수준 (var window: UIWindow?) 바로 아래로 이동합니다. 그렇게하면 소리가 제대로 재생되고 경고음이 제대로 표시됩니다.

나는 왜 그렇게 작동하는지 이해하지 못합니다. 내가 놓친 게 있니? 내 문제를 해결하는 적절한 방법입니까?

미리 이해해 주시고 도움을 주실 수있는 모든 분들께 감사드립니다.

답변

3

이미 문제에 대한 올바른 해결책을 제공해 주셨습니다. 클래스 레벨 audioPlayer 속성을가집니다. 이게 왜 그렇게? 코드에서 플레이어를 설정하고, 재생을 시작하고, 팝업을 표시하고, 모든 것이 완료된 후에 메소드가 범위를 종료하기 때문입니다. 자동 메모리 관리 (ARC)는 해당 변수의 범위를 종료 할 때 모든 지역 변수가 해제되도록 작동합니다. 사운드 재생이 비동기 적이라고 생각하면 (예 : 메인 스레드를 차단하지 않고 재생됩니다) 오디오 플레이어의 사운드 재생이 끝나기 전에 스코프를 종료합니다. ARC는 audioPlayer이 로컬 변수이며 그 시점에서 해제한다는 것을 알지만 사운드는 아직 재생되지 않습니다.

내가 충분히 명확하면, 더 이상 물어 보지 않겠습니까?

+0

나는 소리 재생을 끝내기 전에 물체가 풀린 것으로 생각됩니다. 그러나 솔루션 2에서는이 수준 (특히 AppDelegate)에서 속성을 배치하는 _bad 연습이 아닙니까? 문제를 해결할 적절한 방법이 없습니까? – lchamp

+0

@lchamp 인스턴스 변수를 갖는 것은 나쁜 습관이 아니며, 전역 변수를 갖는 것은 좋지 않습니다. 그러나 나는 애플 리케이션 델리게이트에서 이것을 갖는 것이 이상적 이진 않는다는 것에 동의한다. 내가 무엇을 할 것인가 (특히 한 번 이상이 소리를 들려 준다면); 당신이 어디에서나 호출 할 수있는 싱글 톤 클래스 (예 : SoundPlayer)를 생성하십시오. 그 클래스에서 실제'AVAudioPlayer'를 보유하는 인스턴스 변수를 추가하십시오. 그런 다음 'SoundPlayer.sharedPlayer.play (SoundType.Alert)'또는 유사한 인터페이스를 사용할 수도 있습니다. –

+0

제안대로 싱글 톤을 만들었습니다. 감사 ! – lchamp

관련 문제