从 CloudKit 获取并保存到 CoreData

Posted

技术标签:

【中文标题】从 CloudKit 获取并保存到 CoreData【英文标题】:fetching from CloudKit and saving to CoreData 【发布时间】:2016-01-28 04:23:39 【问题描述】:

这将是一个非常菜鸟的问题,但我正试图让我的应用程序从 CloudKit 下载数据,然后将其保存到 CoreData。

当我运行这种类型的代码时,我收到以下错误。我真的是 CoreData 的菜鸟,所以这对我来说很难理解。我认为这与我发送请求的方式有关,但我不确定我应该如何解决它。我得到的错误是:

由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“recordChangeSnapshot:forObjectID:: 录制时全局 ID 可能不是临时的 '

有人有什么想法吗?

import UIKit
import CloudKit
import CoreData

class Start: UIViewController 

    var clas-s-roomEN: String?
    var clas-s-roomTC: String?
    var clas-s-roomSC: String?

    var videos = [NSManagedObject]()

    override func viewDidLoad() 

        fetchData()
        fetchDataTC()
    

    func fetchData() 

        //added to fetch data from CloudKit
        let container = CKContainer.defaultContainer()
        let publicData = container.publicCloudDatabase

        let predicate = NSPredicate(value: true)

        let queryEN = CKQuery(recordType: "Clas-s-roomFAQEN", predicate: predicate)
        let queryTC = CKQuery(recordType: "Clas-s-roomFAQTC", predicate: predicate)

        queryEN.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
        queryTC.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]

        publicData.performQuery(queryEN, inZoneWithID: nil)  results, error in

            if error == nil  // There is no error

                for entry in results! 
                    let newFAQ = classFAQ()
                    newFAQ.title = entry["Title"] as! String
                    newFAQ.content = entry["Content"] as! String
                    if entry["Picture"] != nil 
                        print("There is no picture")
                        newFAQ.picture = entry["Picture"] as! String
                    
                    if entry["Video"] != nil 
                        print("There is no video")
                        newFAQ.video = entry["Video"] as! String
                    

                    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
                    let managedContext = appDelegate.managedObjectContext
                    let entity =  NSEntityDescription.entityForName("Clas-s-roomFAQEN", inManagedObjectContext:managedContext)
                    let video = NSManagedObject(entity: entity!, insertIntoManagedObjectContext: managedContext)
                    video.setValue(newFAQ.title, forKey: "title")
                    video.setValue(newFAQ.content, forKey: "content")
                    video.setValue(newFAQ.picture, forKey: "picture")
                    video.setValue(newFAQ.video, forKey: "video")

                    do 
                        try video.managedObjectContext!.save()
                        self.videos.append(video)
                     catch let error as NSError  
                        print("Could not save \(error), \(error.userInfo)")
                    

                    dispatch_async(dispatch_get_main_queue(),  () -> Void in
                        print("Reloading data in tableView")
                        self.fetchDataTC()
                    )
                
            
            else 
                print(error)
            
        
    

    func fetchDataTC() 

        //added to fetch data from CloudKit
        let container = CKContainer.defaultContainer()
        let publicData = container.publicCloudDatabase

        let predicate = NSPredicate(value: true)

        let queryEN = CKQuery(recordType: "Clas-s-roomFAQEN", predicate: predicate)
        let queryTC = CKQuery(recordType: "Clas-s-roomFAQTC", predicate: predicate)

        queryEN.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
        queryTC.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]

        publicData.performQuery(queryTC, inZoneWithID: nil)  results, error in

            if error == nil  // There is no error

                for entry in results! 
                    let newFAQ = classFAQ()
                    newFAQ.title = entry["Title"] as! String
                    newFAQ.content = entry["Content"] as! String
                    if entry["Picture"] != nil 
                        print("There is no picture")
                        newFAQ.picture = entry["Picture"] as! String
                    
                    if entry["Video"] != nil 
                        print("There is no video")
                        newFAQ.video = entry["Video"] as! String
                    

                    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
                    let managedContext = appDelegate.managedObjectContext
                    let entity =  NSEntityDescription.entityForName("Clas-s-roomFAQTC", inManagedObjectContext:managedContext)
                    let video = NSManagedObject(entity: entity!, insertIntoManagedObjectContext: managedContext)
                    video.setValue(newFAQ.title, forKey: "title")
                    video.setValue(newFAQ.content, forKey: "content")
                    video.setValue(newFAQ.picture, forKey: "picture")
                    video.setValue(newFAQ.video, forKey: "video")

                    do 
                        try video.managedObjectContext!.save()
                        self.videos.append(video)
                     catch let error as NSError  
                        print("Could not save \(error), \(error.userInfo)")
                    

                    dispatch_async(dispatch_get_main_queue(),  () -> Void in
                        print("Reloading data in tableView")
                    )
                
            
            else 
                print(error)
            
        

    

【问题讨论】:

这个对“video.managedObjectContext!.save()”的调用是在后台线程上发生的吗?它通常在主线程上调用。 感谢发帖。抱歉,如何保存到主线程? 【参考方案1】:

您可以使用isMainThread 来确定您是否在后台线程中.. 或者您可以直接编写这样的代码,这将始终确保它在主线程中:-

    dispatch_async(dispatch_get_main_queue(),  () -> Void in
                        do 
                        try video.managedObjectContext!.save()
                        self.videos.append(video)
                     catch let error as NSError  
                        print("Could not save \(error), \(error.userInfo)")
                    
                    )

【讨论】:

您的代码有误。有什么建议吗?一元运算符!不能应用于 () 类型的操作数 -> Bool 嗨 Vizllx,它似乎有效。但是我遇到了问题。每当我运行该应用程序时,它都不会收集我的 CloudKit 数据库中的所有条目。例如,在 Clas-s-roomFAQEN 类实体中,有 9 个条目。我只得到其中的1-3个。知道为什么会这样吗?

以上是关于从 CloudKit 获取并保存到 CoreData的主要内容,如果未能解决你的问题,请参考以下文章

保存和获取 CloudKit 引用

使用 MagicalRecord 保存实体 - 还尝试保存不同的实体?

如何使用 Cloudkit 快速从 iCloud 获取当前用户信息

iOS swift:使用 coredata (cloudkit) 存储缓存

如何使用 CloudKit 将条目从公共数据库保存到私有数据库

CloudKit 订阅内部服务器错误