核心数据更新旧项目,创建新记录

时间:2016-01-01 16:42:01

标签: ios swift core-data cloudkit

我正在使用iOS 9 / Xcode 7 / Swift 2构建iOS应用

主数据存储区是Cloudkit,这种方法很好(但速度很慢),并允许用户之间共享数据。

为了加快大多数查询的过程,Core Data正在本地使用。

更新核心数据时,会出现两种状态 - 1.从CloudKit向Core数据添加一条新记录(这似乎工作正常) 2.从CloudKit更新现有核心数据记录(这是有问题的步骤!)

是否应删除现有核心数据记录,然后创建新记录或其他解决方案?

这是迄今为止的代码 -

from importlib import import_module

1 个答案:

答案 0 :(得分:1)

这是这一行:

let localFoodItem = NSManagedObject(entity: entityDescription!, insertIntoManagedObjectContext: self.managedObjectContext)

创建新的CoreData记录。后续for循环的每次迭代只会更改这一条记录的属性值,因此即使从CloudKit有几个要同步的项目,也只会创建一个新的CoreData记录。上面的行应该在for循环中。由于您只想创建一个新的CoreData对象,如果没有相同upc的预先存在的对象,则上面的行应该在else子句中。如果存在预先存在的对象,我假设您只想使用CloudKit中的新值更新该对象的其他属性:

let entityDescription = NSEntityDescription.entityForName("FoodItem", inManagedObjectContext: self.managedObjectContext)
let syncpredicate = NSPredicate(value: true)
let syncquery = CKQuery(recordType: "Food", predicate: syncpredicate)
publicDatabase.performQuery(syncquery, inZoneWithID: nil) { results, error in
    if error == nil { // There is no error
        var numberAdded = 0
        var numberUpdated = 0
        for entry in results! {
            let cloudUPC = entry["UPC"] as? String
            //print("UPC from CloudKit \(cloudUPC)")
            let cloudFoodName = entry["foodName"] as? String
            //print("Name from CloudKit \(cloudFoodName)")
            let cloudIngredients = entry["ingredients"] as? String
            //print("Ingredients from CloudKit \(cloudFoodName)")

            let corepredicate = NSPredicate(format: "upc = %@", cloudUPC!)
            // Initialize Fetch Request
            let fetchRequest = NSFetchRequest()
            fetchRequest.predicate = corepredicate
            fetchRequest.entity = entityDescription

            var error: NSError?
            do {
                let result = try self.managedObjectContext.executeFetchRequest(fetchRequest)
                if result.count > 0 {
                    let match = result[0] as! NSManagedObject
                    print("FoodItem Found in CoreData")
                    // The next three lines seem superfluous?
                    let upcNumber = match.valueForKey("upc") as! String
                    let iList = match.valueForKey("ingredients") as! String
                    let coreName = match.valueForKey("productName") as! String
                    print("Item UPDATED in CoreData")
                    match.setValue(cloudFoodName, forKey: "productName")
                    match.setValue(cloudIngredients, forKey: "ingredients")
                    numberUpdated++
                } else {
                    print("IMPORTED New Item from CloudKit")
                    let localFoodItem = NSManagedObject(entity: entityDescription!, insertIntoManagedObjectContext: self.managedObjectContext)
                    localFoodItem.setValue(cloudUPC, forKey: "upc")
                    localFoodItem.setValue(cloudFoodName, forKey: "productName")
                    localFoodItem.setValue(cloudIngredients, forKey: "ingredients")
                    numberAdded++
                }
            } catch let error as NSError {
                // failure
                print("Fetch failed: \(error.localizedDescription)")
            }
        }
        do {
            try self.managedObjectContext.save()
            print("Database Additions: \(numberAdded)")
            print("Database Updates: \(numberUpdated)")
        } catch {
            print(error)
        }
    }else {
        print(error)
    }
}

请注意,我会移动save操作,使其在for循环之后,而不是在for循环之内。另外,如果没有在主线程上执行CloudKit完成处理程序,你可能会发现你有CoreData线程/并发问题(我不熟悉CK所以不能建议)。