Cloudkit 共享更新核心数据 NSManaged 对象

如何解决Cloudkit 共享更新核心数据 NSManaged 对象

我有一个简单的购物清单应用程序,它在 Cloudkit 中使用 Core Data。用户创建一个列表,然后将项目添加到列表中。该列表可以共享给其他用户。 Core Data 首先用于将 Lists 和 Items 保存为 NSManaged Objects。然后将列表共享给可以将项目添加到列表的另一个用户,并且在同一列表上工作的两个用户彼此保持同步。这大部分都在工作,但我在获取 Core Data 以使用 Cloud Kit Share 中的更改更新本地存储的 NSManaged 对象时遇到了一些麻烦。

目前,该应用程序正在处理 NSManaged Objects 和 CKRecords 的混合,以显示在显示列表中项目的表视图中。这有点乱。我真的很想使用 Cloudkit 来处理 NSManaged Objects,从而在 2 个用户之间保持同步。

当用户 B 添加一个项目时,它成功地保存到共享数据库并将父项设置为共享列表。这是我有点卡住的地方,因为我希望用户 A 看到用户 B 添加的项目,并且我想使用 CloudKit 在后台创建的 NSManaged 对象来更新 UI。

在后台 Cloudkit 看到用户 B 添加到共享数据库中的新 CKRecord 并为用户 A 创建一个新的 NSManaged 对象。当应用程序转到 Cloudkit 时,我只能获取核心数据来保存新的 NSManaged Object Cloudkit后台或关闭然后重新启动。我确实等待了大约一分钟以确保同步发生。检查用户 A 的 Sqlite 数据库,用户 B 添加的新项目不在那里。当应用程序进入后台并且我再次检查 Sqlite 数据库时,然后添加了项目。看起来 Cloudkit 制作的 NSManaged 对象只有在应用进入后台时才会保存到 Core Data 中。

长话短说,有没有办法让 Core Data 保存 CloudKit 创建的 NSManaged 对象,而无需应用程序进入后台?

这是我设置容器的代码,我确实有设置远程通知和推送通知的权利。此外 (application.registerForRemoteNotifications()) 在 App 委托中设置。我在这里遗漏了什么吗?

 lazy var persistentContainer: NSPersistentCloudKitContainer = {

    let container = NSPersistentCloudKitContainer(name: "Shopping_List")
    
    let description = container.persistentStoreDescriptions.first
            description?.setOption(true as NSNumber,forKey: NSPersistentHistoryTrackingKey)
    
    // listen for remote notifications
    let remoteChangeKey = "NSPersistentStoreRemoteChangeNotificationOptionKey"
    
       description?.setOption(true as NSNumber,forKey: remoteChangeKey)

 
    container.loadPersistentStores(completionHandler: { (storeDescription,error) in
        if let error = error as NSError? {

            fatalError("Unresolved error \(error),\(error.userInfo)")
        }
   
    })
    
    
    container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
    
    
    container.viewContext.automaticallyMergesChangesFromParent = true
    
 
    
    return container
    
}()

这是在共享数据库中添加新项目的代码

  let saveAction = UIAlertAction(title: "Add",style: .default) { [self] (alert) in
   
               if itemNameTextField.text != "" || itemNameTextField.text != nil {
                
   
                 //CLOUD KIT ADD ITEM - IF LIST IS A CKRECORD IT IS SHARED FROM CLOUD KIT. CREATE A NEW ITEM AS A CKRECORD SAVE TO SHARE
                
                let ckRecord = selectedList as? CKRecord
                
                if ckRecord != nil {
         
                 // get the parent record ID as a string.  Used to set the CD_Parent List property of the new record
                    let parentListId = ckRecord!.recordID.recordName
                    
                 // create a new record ID using the selected list's record zone ID.  Need this to create the new record setting its Zone ID the same as the parent.
                    
                    let newItemID = CKRecord.ID(zoneID: ckRecord!.recordID.zoneID)
                    
                    // create new CKRecord,setting the Type of record
                    
                    let ckNewItem = CKRecord(recordType: "CD_Item",recordID: newItemID)
                    
                    
                    
                    // set the a value for a key.  The value has to be downcast as a CKRecord Value.  The value must also match the datatype that has been set for key.  Check the Core Data to see which attributes(keys) have which data types.  Attirbute names are all the same only difference is for cloud kit it has "CD_" prefixed.
                    
                    ckNewItem.setObject(itemNameTextField.text as CKRecordValue?,forKey: "CD_itemName")
                    
                    // get the string value as a Int 64 number from the text field.  The number of items attribute is an Integer not string.
                    let number = Int64(numberOfItemsTextField.text ?? "1") ?? 1
                    
                    ckNewItem.setObject(number as CKRecordValue,forKey: "CD_numberOfItems")
                    
                    ckNewItem.setObject(false as CKRecordValue,forKey: "CD_done")
                    
                    ckNewItem.setObject(parentListId as CKRecordValue,forKey: "CD_parentList")
                    
                    ckNewItem.setObject("Item" as CKRecordValue,forKey: "CD_entityName")
                    
                   
                    
                    // set the parent as the selected list - create a CK reference based on the selected list
                    
                    ckNewItem.parent = CKRecord.Reference(record: ckRecord!,action: .none)
                    
                    // save the newCKRecord to the shared Database
                    
                    container.saveRecord(ckNewItem,on: container.sharedCloudDatabase) { (record,error) in
                        
                        if error != nil {
                            
                            //show error to user.
                            
                            print ("Error Saving Record")
                        }
                        
                        if let safeRecord = record {
                            
                            self.loadedItems.append(safeRecord)
                            
                            DispatchQueue.main.async {
                                
                                tableView.reloadData()
                            }
                            
                        }
                       
                    }
                  
                }
                

            }
   
        }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)> insert overwrite table dwd_trade_cart_add_inc > select data.id, > data.user_id, > data.course_id, > date_format(
错误1 hive (edu)> insert into huanhuan values(1,'haoge'); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive> show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 <configuration> <property> <name>yarn.nodemanager.res