swift – CoreData使用nil属性创建和保存额外的实体
我有一个联系人表和位置表,每个联系人都有许多位置
我创建一个联系人保存,然后创建一个位置并保存,然后将保存的位置分配给联系人.代码如下: @IBAction func saveLocation(_ sender: AnyObject) { let processName = ProcessInfo.processInfo.globallyUniqueString let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext let location = Location(context: context) do { let fetchRequest: NSFetchRequest<Contact> = Contact.fetchRequest() fetchRequest.predicate = NSPredicate(format: "uniqueId == %@",contactIdentifierString) let fetchedResults = try context.fetch(fetchRequest) if let aContact = fetchedResults.first { // set location data location.uniqueId = processName location.locationName = locationNameTextField.text location.city = self.city location.state = self.state location.street = self.street location.zip = self.zip location.country = self.country // save data (UIApplication.shared.delegate as! AppDelegate).saveContext() location.contact = aContact myDelegate?.userSelectedContact(contactIdentifier: contactIdentifierString,locationIdentifier: processName) } } catch { print ("fetch task failed",error) } // Check results do { let fetchRequest: NSFetchRequest<Location> = Location.fetchRequest() fetchRequest.predicate = NSPredicate(format: "uniqueId == %@",processName) let fetchedResults = try context.fetch(fetchRequest) if let aLocation = fetchedResults.first { print("+++++==========++++++++++") print("Location.Contact: (aLocation.contact)") print("+++++==========++++++++++") } } catch { print ("location fetch failed") } self.navigationController!.popViewController(animated: true) } 我只添加了一个位置,但是当我打印联系人实体时,我看到分配了两个位置,如下所示.
您很可能在某些情况下调用saveLocation,其中fetch失败或没有结果与谓词匹配,saveLocation无法正确处理这些情况.
的init(背景:) NSManagedObject上的此初始化程序不仅在调用Location(context:context)时在内存中创建一个空的Location对象,而且还将该对象插入到您传递的托管对象上下文中.一旦调用了saveContext(),该Location对象(如果没有进一步编辑它将为空)将被保留. 虽然init(context:)没有详细记录,但Apple似乎表明它与init(entity:insertInto:)的工作方式相同,只是该实体被自动计算出来. 保存位置(:) 在此函数中,您已创建了Location对象… let location = Location(context: context) …在检查联系人是否存在并设置属性之前. if let aContact = fetchedResults.first 因此,如果发生提取失败或提取返回0结果,则在调用初始化程序时创建的空位置对象将保留在上下文中,以便在下次任何人调用saveContext()时保留. 解决方案和预防 在这种特殊情况下,您可能会发现在移动此行后您的问题将得到解决 let location = Location(context: context) 到下面的if let块: if let aContact = fetchedResults.first { // create location here,not at beginning of method let location = Location(context: context) // set location data location.uniqueId = processName location.locationName = locationNameTextField.text location.city = self.city location.state = self.state location.street = self.street location.zip = self.zip location.country = self.country // save data (UIApplication.shared.delegate as! AppDelegate).saveContext() location.contact = aContact myDelegate?.userSelectedContact(contactIdentifier: contactIdentifierString,locationIdentifier: processName) } 作为在使用Core Data时可以防止此问题的一般规则,不要在任何NSManagedObject子类上使用init(context :),除非您首先执行了所有必要的检查并确定要立即将项插入上下文. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |