当应用程序在后台Swift中时,PerformBackgroundTask无法保存

时间:2018-08-30 08:27:06

标签: ios json swift core-data background

我正在使用Xcode 9和Swift4。当应用程序位于前台时,我开始下载多个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

1 个答案:

答案 0 :(得分:5)

使用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:方法。它使系统知道您已完成。如果您不及时结束任务,系统将终止您的应用程序。