我想实现以下功能:
我需要在接收到推送通知时使用urlSessionDownloadTask下载文件。收到推送通知后,我开始使用urlSessionBackgroundTask下载文件。该文件已成功下载。 然后,我使用批量插入将文件中的所有记录插入到coredata中。
如果应用程序在前台或后台运行,则一切正常。
但是,当应用程序未运行/处于终止状态时,在收到推送通知时,上述过程将不起作用。
在检查设备日志时,我发现崩溃==>调度队列:com.apple.main-thread
任何帮助将不胜感激。
AppDelegate
func onPushReceived(_ pushManager: PushNotificationManager!, withNotification pushNotification: [AnyHashable : Any]!, onStart: Bool) {
print("Push notification received: \(pushNotification)")
//after identifying the push
syncManager.downloadFile()
}
SyncManager
func downloadFile() {
let url = URL(string: "my url")!
let task = DownloadTaskManager.shared.activate().downloadTask(with: url)
task.earliestBeginDate = Date().addingTimeInterval(60 * 1)
task.resume()
DownloadTaskManager.shared.onTaskCompleted = { () in
self.updateProductsStatus()
}
}
DownloadTaskManager
class DownloadTaskManager : NSObject {
static var shared = DownloadTaskManager()
var onTaskCompleted: () -> () = {}
var isTaskCompleted = false {
didSet {
self.onTaskCompleted()
}
}
let group = DispatchGroup()
override private init() {
super.init()
}
func activate() -> URLSession {
let config = URLSessionConfiguration.background(withIdentifier:"backgroundTask")
config.isDiscretionary = true
config.sessionSendsLaunchEvents = true
return URLSession(configuration: config, delegate: self, delegateQueue: nil)
}
}
extension DownloadTaskManager: URLSessionDelegate, URLSessionDownloadDelegate {
private func readProductsFromDatabase() -> Bool {
var pageNo = 0
group.enter()
DispatchQueue.main.async {
guard let managedContext = UIApplication.appDelegate?.getContext() else {
fatalError("context not found")
}
let _ = DatabaseManager.deleteRecords(context: managedContext, entity: EntityType.product.rawValue)
while(true) {
let products = DatabaseManager.fetchProductsFromLocalDb(page: pageNo)
let _ = DatabaseManager.insertBatchOfProducts(inManagedObjectContext: managedContext, productArray: products)
if products.count < 1000 {
let products = DatabaseManager.getAllProducts(inManagedObjectContext: managedContext)
self.isTaskCompleted = true
break
} else {
pageNo = pageNo + 1
}
}
}
group.wait()
return true
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
debugPrint("Download finished: \(location)")
guard let httpResponse = downloadTask.response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
print ("server error")
return
}
do {
let downloadedData = try Data(contentsOf: location)
let documentDirectoryPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! as NSString
let destinationPath = documentDirectoryPath.appendingPathComponent("Database.db")
let databaseFileUrl = URL(fileURLWithPath: destinationPath)
FileManager.default.createFile(atPath: databaseFileUrl.path,
contents: downloadedData,
attributes: nil)
if FileManager.default.fileExists(atPath: databaseFileUrl.path) {
print("File present!") // Confirm that the file is here!
}
try FileManager.default.removeItem(at: location)
let _ = readProductsFromDatabase()
try FileManager.default.removeItem(at: databaseFileUrl)
} catch {
print(error.localizedDescription)
}
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
debugPrint("Task completed: \(task), error: \(error)")
}
func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
DispatchQueue.main.async {
if let appDelegate = UIApplication.appDelegate {
if let completionHandler = appDelegate.backgroundSessionCompletionHandler {
appDelegate.backgroundSessionCompletionHandler = nil
completionHandler()
}
}
}
}
}