簡體   English   中英

如何使Alamofire下載進度在后台ios中運行?

[英]how to make alamofire download progress run in background ios?

我正在使用Alamofire下載數據

如何快速運行alamofire在后台運行下載?

謝謝

基本思想如下:

  1. 關鍵問題在於,使用后台下載,您的應用實際上可能會在下載進行過程中終止(例如,由於內存不足而被拋棄)。 幸運的是,在完成后台下載后,您的應用再次啟動,但是您最初提供的任何任務級關閉都已一去不復返了。 為了解決這個問題,在使用后台會話時,應該依靠委托方法使用的會話級關閉。

     import UIKit import Alamofire import UserNotifications fileprivate let backgroundIdentifier = ... fileprivate let notificationIdentifier = ... final class BackgroundSession { /// Shared singleton instance of BackgroundSession static let shared = BackgroundSession() /// AlamoFire `SessionManager` /// /// This is `private` to keep this app loosely coupled with Alamofire. private let manager: SessionManager /// Save background completion handler, supplied by app delegate func saveBackgroundCompletionHandler(_ backgroundCompletionHandler: @escaping () -> Void) { manager.backgroundCompletionHandler = backgroundCompletionHandler } /// Initialize background session /// /// This is `private` to avoid accidentally instantiating separate instance of this singleton object. private init() { let configuration = URLSessionConfiguration.background(withIdentifier: backgroundIdentifier) manager = SessionManager(configuration: configuration) // specify what to do when download is done manager.delegate.downloadTaskDidFinishDownloadingToURL = { _, task, location in do { let destination = try FileManager.default.url(for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: false) .appendingPathComponent(task.originalRequest!.url!.lastPathComponent) try FileManager.default.moveItem(at: location, to: destination) } catch { print("\\(error)") } } // specify what to do when background session finishes; ie make sure to call saved completion handler // if you don't implement this, it will call the saved `backgroundCompletionHandler` for you manager.delegate.sessionDidFinishEventsForBackgroundURLSession = { [weak self] _ in self?.manager.backgroundCompletionHandler?() self?.manager.backgroundCompletionHandler = nil // if you want, tell the user that the downloads are done let content = UNMutableNotificationContent() content.title = "All downloads done" content.body = "Whoo, hoo!" let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false) let notification = UNNotificationRequest(identifier: notificationIdentifier, content: content, trigger: trigger) UNUserNotificationCenter.current().add(notification) } // specify what to do upon error manager.delegate.taskDidComplete = { _, task, error in let filename = task.originalRequest!.url!.lastPathComponent if let error = error { print("\\(filename) error: \\(error)") } else { print("\\(filename) done!") } // I might want to post some event to `NotificationCenter` // so app UI can be updated, if it's in foreground } } func download(_ url: URL) { manager.download(url) } } 
  2. 然后,我可以啟動這些下載。 請注意,在啟動下載時,我沒有指定任何特定於任務的關閉,而是僅使用上面的會話級關閉,這些關閉使用URLSessionTask的詳細信息來確定要執行的操作:

     class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // request permission to post notification if download finishes while this is running in background UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { granted, error in if let error = error, !granted { print("\\(error)") } } } @IBAction func didTapButton(_ sender: Any) { let urlStrings = [ "http://spaceflight.nasa.gov/gallery/images/apollo/apollo17/hires/s72-55482.jpg", "http://spaceflight.nasa.gov/gallery/images/apollo/apollo10/hires/as10-34-5162.jpg", "http://spaceflight.nasa.gov/gallery/images/apollo-soyuz/apollo-soyuz/hires/s75-33375.jpg", "http://spaceflight.nasa.gov/gallery/images/apollo/apollo17/hires/as17-134-20380.jpg", "http://spaceflight.nasa.gov/gallery/images/apollo/apollo17/hires/as17-140-21497.jpg", "http://spaceflight.nasa.gov/gallery/images/apollo/apollo17/hires/as17-148-22727.jpg" ] let urls = urlStrings.flatMap { URL(string: $0) } for url in urls { BackgroundSession.shared.download(url) } } } 
  3. 如果下載完成后您的應用程序未運行,則iOS需要在重新啟動應用程序后知道該操作何時完成,並且可以安全地掛起您的應用程序。 因此,在handleEventsForBackgroundURLSession您可以捕獲該閉包:

     class AppDelegate: UIResponder, UIApplicationDelegate { ... func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) { BackgroundSession.shared.saveBackgroundCompletionHandler(completionHandler) } } 

    在步驟1中,由sessionDidFinishEventsForBackgroundURLSession使用。

    兩個觀察:

    • 僅當下載完成后您的應用未運行時才調用此方法。

    • 但是,如果進行后台會話,則必須捕獲此閉包並在處理完后台會話委托方法之后調用它。

因此,回顧一下,后台會話的基本限制是:

  • 您只能在應用程序處於后台狀態時使用下載和上傳任務;

  • 您只能依賴會話級委托,因為自發起請求以來,該應用可能已終止;

  • 在iOS中,您必須實現handleEventsForBackgroundURLSession ,捕獲該完成處理程序,並在后台進程完成后調用它。

我還必須指出,盡管Alamofire是一個很棒的庫,但實際上並沒有增加太多價值(超出URLSessionURLSession下載過程中提供的URLSession )。 如果僅執行簡單的上載/下載,則可以考慮直接使用URLSession 但是,如果您已經在項目中使用了Alamofire,或者您的請求包含更復雜的application/x-www-form-urlencoded請求(或其他任何請求),這些都值得Alamofire的優點,那么以上內容概述了與處理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM