Скачать AlamoFire в фоновом режиме
Я использую Alamofire в новом приложении (образец диспетчера загрузки на основе Alamofire). Мне нужны некоторые разъяснения о загрузке файлов с использованием фонового сеанса. Мне нужно переопределить SessionDelegate, чтобы он работал? Или просто backgroundCompletionHandler
?
Каковы шаги для обработки загрузок в фоновом режиме с использованием Alamofire? И как я могу справиться со случаем, когда мое приложение обновлено, с загрузками в потоке.
Ответы
Ответ 1
Update
Основываясь на этом удивительном учебнике, я собрал примерный проект, доступный на GitHub. Он имеет пример управления фоновым сеансом.
Согласно Apple Руководство по программированию URL-адреса URL:
В iOS и OS X, когда пользователь перезагружает ваше приложение, ваше приложение должен немедленно создавать фоновые объекты конфигурации с помощью те же идентификаторы, что и любые сеансы, у которых были приложение было выполнено в последний раз, затем создайте сеанс для каждого из этих объекты конфигурации. Эти новые сеансы аналогично автоматически reassociated с текущей фоновой деятельностью.
Таким образом, по-видимому, используя соответствующие экземпляры конфигурации фонового сеанса, ваши загрузки никогда не будут "in flux".
Я также нашел этот ответ действительно полезным.
Оригинальный ответ
Из Alamofire Страница GitHub:
Приложения могут создавать менеджеров для фона и эфемерных сессий, а также новых менеджеров, которые настраивают сеанс по умолчанию конфигурации, например, для заголовков по умолчанию (HTTPAdditionalHeaders) или тайм-аут (timeoutIntervalForRequest).
По умолчанию методы верхнего уровня используют общий экземпляр Manager
с настройкой сеанса по умолчанию. Однако вы можете создать менеджера с настройкой фонового сеанса следующим образом:
let configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier("com.example.app.background")
let manager = Alamofire.Manager(configuration: configuration)
Затем вы можете создавать запросы, используя этот Manager
экземпляр.
manager.startRequestsImmediately = true
let request = NSURLRequest(URL: NSURL(string: "your.url.here")!)
manager.request(request)
Изучая его реализацию, он также имеет свойство backgroundCompletionHandler
, поэтому вы можете добавить блок завершения:
manager.backgroundCompletionHandler = {
// do something when the request has finished
}
Ответ 2
На Alamofire это очень легко:
1) ваш Alamofire.Manager должен быть настроен с идентификатором фонового сеанса:
class NetworkManager {
...
private lazy var backgroundManager: Alamofire.SessionManager = {
let bundleIdentifier = ...
return Alamofire.SessionManager(configuration: URLSessionConfiguration.background(withIdentifier: bundleIdentifier + ".background"))
}()
...
}
2) в App Delegate реализуют application(_:handleEventsForBackgroundURLSession:completionHandler:
и передают обработчик завершения Alamofire.SessionManager.backgroundCompletionHandler
.
В моем случае метод делегирования приложения выглядит как
func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
NetworkManager.default.backgroundCompletionHandler = completionHandler
}
и мой менеджер сети имеет вычисленное свойство, подобное этому, чтобы установить свойство Manager:
var backgroundCompletionHandler: (() -> Void)? {
get {
return backgroundManager.backgroundCompletionHandler
}
set {
backgroundManager.backgroundCompletionHandler = newValue
}
}
Ответ 3
Я искал решение довольно долго. До тех пор, пока не прочитайте упомянутую выше статью. Проблема для меня была - мне пришлось включить внешнюю связь
![enter image description here]()
Все остальное было сделано, как описано выше. AppDelegate:
func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
BackendAPIManager.sharedInstance.backgroundCompletionHandler = completionHandler
}
Синглтон:
import Alamofire
class BackendAPIManager: NSObject {
static let sharedInstance = BackendAPIManager()
var alamoFireManager : Alamofire.SessionManager!
var backgroundCompletionHandler: (() -> Void)? {
get {
return alamoFireManager?.backgroundCompletionHandler
}
set {
alamoFireManager?.backgroundCompletionHandler = newValue
}
}
fileprivate override init()
{
let configuration = URLSessionConfiguration.background(withIdentifier: "com.url.background")
configuration.timeoutIntervalForRequest = 200 // seconds
configuration.timeoutIntervalForResource = 200
self.alamoFireManager = Alamofire.SessionManager(configuration: configuration)
}
}
И звонки выполняются следующим образом:
BackendAPIManager.sharedInstance.alamoFireManager.upload(multipartFormData: { (multipartFormData) in ...
Ответ 4
BackendAPIManager.sharedInstance.alamoFireManager!.download(url,to:destination).downloadProgress { (progress) in
self.UpdateProgress(progress: progress.fractionCompleted)
}
.responseData { (data) in
if data.error == nil
{
self.DownloadComplete()
}
else
{
self.DowonloadFiled()
}
}
Все отлично работает, но когда приложение переходит в фоновый режим, оно возвращается в forground
self.UpdateProgress(progress: progress.fractionCompleted)
не называть. Как это исправить?