Как использовать делегаты URLSession с запланированной средой BackgroundTasks - PullRequest
0 голосов
/ 09 января 2020

Я пробую свой первый код с помощью инфраструктуры Apple BackgroundTasks, чтобы запланировать загрузку файлов с удаленного веб-сайта на периодической основе c. Эти файлы содержат обновленные данные, необходимые моему приложению для выполнения своих операций. У меня есть существующий класс с именем PopularDataDownloader, который загружает файл в фоновом режиме, используя URLSession, как показано ниже:

class PopularDataDownloader: NSObject{
    var downloadTask: URLSessionDownloadTask?

    lazy var downloadsSession: URLSession = {
        let configuration = URLSessionConfiguration.background(withIdentifier: "MY-UNIQUE-IDENTIFIER")


        return URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
    }()

    func startDownload(url: URL){
        let downloadTask = downloadsSession.downloadTask(with: url)
        downloadTask.resume()
        self.downloadTask = downloadTask
    }
}


extension PopularDataDownloader: URLSessionDownloadDelegate {
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
        guard let sourceURL = downloadTask.originalRequest?.url else {
            return
        }
        print("Finished downloading...")
        print(location)
        // process file...
    }
}

Этот логический c, описанный до сих пор, работает так, как задумано, когда инициируется через взаимодействие с пользователем (например, нажатие кнопки). ) в приложении. Моя проблема в том, что я не уверен, как подключить это так, чтобы это могло быть запланировано через инфраструктуру BackgroundTasks. В моем AppDelegate у меня есть следующий код:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.test.data.refresh", using: nil) { (task) in
        self.handleDataRefresh(task: task as! BGAppRefreshTask)
    }
    return true
}
func handleDataRefresh(task: BGAppRefreshTask) {
    task.expirationHandler = {
        task.setTaskCompleted(success: false)
    }

    let downloader = PopularDataDownloader()
    downloader.startDownload(url: URL(string: "URL_FOR_DATA")!)    
    task.setTaskCompleted(success: true)

    scheduleBackgroundDataRefresh()
}


func scheduleBackgroundDataRefresh() {
    let task = BGAppRefreshTaskRequest(identifier: "com.test.data.refresh")
    task.earliestBeginDate = Date(timeIntervalSinceNow: 60)
    do {
      try BGTaskScheduler.shared.submit(task)
    } catch {
      print("Unable to submit task: \(error.localizedDescription)")
    }
}

Я вижу, как запускаются запланированные задачи, но моя проблема заключается в том, что вызов startDownload возвращается немедленно и до завершения загрузки файла и обрабатывается, так как URLSessionDownloadDelegate является где эта логика c происходит. Мой вопрос заключается в том, как мне реализовать запланированную фоновую задачу, основанную на возможностях делегирования URLSession? Можно ли реализовать замыкание (обработчик завершения) для функции startDownload, которая затем сохраняется и затем используется в делегате? Есть какой-то другой дизайн, который я должен использовать?

...