2017-05-09 4 views
2

AVAudioPlayer를 사용하여 레코드를 재생하고 있습니다. 각 재생 세션 사이에는 0 ~ 10 초 간격이 있습니다. 내가 AVAudioPlayerDelegate을 사용하고이 간격을 만들려면 및 완료 연주 할 때 나는 지연 후 새로운 재생을 시작 해요 :앱이 백그라운드/비활성 상태 인 경우 GCD`asyncAfter`이 시작되지 않습니다.

func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) { 
    guard let session = playbackSessionId, 
      let audioTrack = audioTrack, 
      let failureHandler = playingFailure, 
      let successHandler = playingSuccess else { 
     playingFinished(flag, error: nil) 
     return 
    } 
    print("audioPlayerDidFinishPlaying fired") 
    DispatchQueue.global(qos: .utility).asyncAfter(deadline: .now() + LoopInterval.currentInterval) { [weak self] in 
     print("asyncAfter fired") 
     guard let strongSelf = self, 
       let currentSession = strongSelf.playbackSessionId, session == currentSession else { return } 
     strongSelf.startPlayingRecordInLoop(audioTrack, success: successHandler, failure: failureHandler) 
    } 
} 
앱이 배경 ( home 버튼), audioPlayerDidFinishPlaying 화재로 이동 한 후

하지만 DispatchQueue.global(qos: .utility).asyncAfter을하지. ,

audioPlayerDidFinishPlaying fired

가 즉시 응용 프로그램으로 활성화 asyncAfter 화재가 난 다음 로그 메시지가 표시됩니다 : 그래서 콘솔에서 나는 볼 응용 프로그램이 활성화되면

asyncAfter fired

이 모든 일이 예상대로.

답변

1

누군가 도움이되기를 바랍니다. 문제가 발견되었습니다. 앱이 백그라운드에서 실행되면 백그라운드 작업이 중지되고 이후에만 실행됩니다. 필요를 피하려면 앱을 백그라운드에서 실행하고 장기간 백그라운드 작업을 기다려야합니다.

backgroundTaskID = UIApplication.shared.beginBackgroundTask(expirationHandler: { 
    UIApplication.shared.endBackgroundTask(backgroundTaskID) 
}) 

이 방법은 앱이 배경으로 전환 한 후 일정 시간 동안 계속 실행 할 수 있습니다. 미완성 된 태스크를 떠나는 것이 앱의 사용자 경험에 해로울 수있는 경우에이 메소드를 호출해야합니다. 예를 들어, 앱이이 메소드를 호출하여 중요한 파일을 원격 서버로 전송하거나 전송을 시도하고 오류를 기록 할 수있는 충분한 시간을 확보 할 수 있습니다. 백그라운드로 이동 한 후에 앱을 계속 실행하려면이 메소드를 사용하면 안됩니다.

작업 완료 후 endBackgroundTask으로 전화해야합니다. backgroundTimeRemaining가 0이 될 때까지 당신은 배경 작업을 종료하지 않을 경우, 응용 프로그램은 종료됩니다 :

UIApplication.shared.endBackgroundTask(backgroundTaskID) 

이 방법에 대한 각 호출은 endBackgroundTask에 일치하는 호출 (:) 방법으로 균형을 이루어야한다. 백그라운드 작업을 실행하는 앱에는 실행할 수있는 시간이 있습니다. backgroundTimeRemaining 속성을 사용하면 시간을 확인할 수 있습니다. 각 작업에 대해 endBackgroundTask ( :)를 호출하지 않으면 시간이 끝나기 전에 시스템이 응용 프로그램을 종료합니다. 핸들러 매개 변수에 블록 객체를 제공하면 시스템은 시간이 만료되기 전에 처리기를 호출하여 작업을 종료 할 수있는 기회를 제공합니다.

func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) { 
    guard let session = playbackSessionId, 
      let audioTrack = audioTrack, 
      let failureHandler = playingFailure, 
      let successHandler = playingSuccess else { 
     playingFinished(flag, error: nil) 
     return 
    } 
    backgroundTaskID = UIApplication.shared.beginBackgroundTask(expirationHandler: { [weak self] in 
     guard let taskId = self?.backgroundTaskID else { return } 
     UIApplication.shared.endBackgroundTask(taskId) 
    }) 
    DispatchQueue.global(qos: .utility).asyncAfter(deadline: .now() + LoopInterval.currentInterval) { [weak self] in 
     guard let strongSelf = self, 
       let currentSession = strongSelf.playbackSessionId, session == currentSession else { return } 
     strongSelf.startPlayingRecordInLoop(audioTrack, success: successHandler, failure: failureHandler) 
     if let backgroundTaskID = strongSelf.backgroundTaskID { 
      UIApplication.shared.endBackgroundTask(backgroundTaskID) 
      strongSelf.backgroundTaskID = nil 
     } 
    } 
} 
: 내 경우에 무슨 짓을했는지