Я пробую свой первый код с помощью инфраструктуры 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, которая затем сохраняется и затем используется в делегате? Есть какой-то другой дизайн, который я должен использовать?