2017-05-09 42 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 
     } 
    } 
} 
相關問題