首页 > 解决方案 > 当应用程序在后台 Swift 中时,performBackgroundTask 不保存

问题描述

我正在使用 Xcode 9 和 Swift 4。当应用程序在前台时,我开始下载多个 JSON 文件。然后应用程序解析这些文件并将它们保存到 CoreData。当应用程序在前台时,这很有效。但是,如果应用程序在后台,文件仍然可以正确下载,但数据不会被解析并保存到 CoreData。只有当用户返回前台时,数据的解析和保存才会继续。

我打开了后台模式 - 后台获取和远程通知。

我有大约 10 个函数,类似于下面的函数,它同时处理 JSON 文件:

func populateStuff(json: JSONDictionary) -> Void {
    let results = json["result"] as! JSONDictionary
    let stuffData = results["Stuff"] as! [JSONDictionary]

    let persistentContainer = getPersistentContainer()

    persistentContainer.performBackgroundTask { (context) in
        for stuff in stuffData {
            let newStuff = Stuff(context: context)
            newStuff.stuffCode = stuff["Code"] as? String
            newStuff.stuffDescription = stuff["Description"] as? String

            do {
                try context.save()
            } catch {
                fatalError("Failure to save context: \(error)")
            }
        }
    }
}

func getPersistentContainer() -> NSPersistentContainer {
    let persistentContainer = NSPersistentContainer(name: "MyProjectName")
    persistentContainer.loadPersistentStores { (_, error) in
        if let error = error {
            fatalError("Failed to load core data stack: \(error.localizedDescription)")
        }
    }
    persistentContainer.viewContext.automaticallyMergesChangesFromParent = true
    persistentContainer.viewContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
    return persistentContainer
}

谁能告诉我为什么会发生这种情况以及如何克服这种情况?

TIA

标签: iosjsonswiftcore-databackground

解决方案


使用beginBackgroundTaskWithName:expirationHandler:方法:

func populateStuff(json: JSONDictionary) -> Void {

    // Perform the task on a background queue.
    DispatchQueue.global().async {

        // Request the task assertion and save the ID.
        self.backgroundTaskID = UIApplication.shared.beginBackgroundTask (withName: "Finish Network Tasks") {

        // End the task if time expires.
        UIApplication.shared.endBackgroundTask(self.backgroundTaskID!)
        self.backgroundTaskID = UIBackgroundTaskInvalid
    }

    // Parse the json files 
    let results = json["result"] as! JSONDictionary
    let stuffData = results["Stuff"] as! [JSONDictionary]

    let persistentContainer = getPersistentContainer()

    persistentContainer.performBackgroundTask { (context) in
        for stuff in stuffData {
            let newStuff = Stuff(context: context)
            newStuff.stuffCode = stuff["Code"] as? String
            newStuff.stuffDescription = stuff["Description"] as? String

            do {
                try context.save()
            } catch {
                fatalError("Failure to save context: \(error)")
            }
        }
    }

    // End the task assertion.
    UIApplication.shared.endBackgroundTask(self.backgroundTaskID!)
    self.backgroundTaskID = UIBackgroundTaskInvalid
}

调用此方法可为您提供额外的时间来执行重要任务。endBackgroundTask:请注意在任务完成后立即使用方法。它让系统知道你已经完成了。如果您没有及时结束您的任务,系统将终止您的应用程序。


推荐阅读