Swift 核心数据关系和种子数据
Posted
技术标签:
【中文标题】Swift 核心数据关系和种子数据【英文标题】:Swift Core Data Relationships and Seeding Data 【发布时间】:2015-07-22 20:55:05 【问题描述】:我目前正在解析 JSON 数据,并根据结果是否存在来更新或创建实体。
我正在使用 SwiftyJson 进行 JSON 解析。
我的 NSManagedObject 子类中有一个 createInManagedObjectContext 函数,它接受一堆用于创建新记录的参数:
class func createInManagedObjectContext(moc: NSManagedObjectContext, id: String, flatNumber: String, propertyName: String, propertyNumber: String, street: String, locality: String, town: String, postcode:String, createdDate: NSString) -> Work
let newWorkItem = NSEntityDescription.insertNewObjectForEntityForName("Work", inManagedObjectContext: moc) as! Work
var mydate = createdDate
let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"
newWorkItem.createdDate = formatter.dateFromString(mydate as String)!
newWorkItem.id = id
newWorkItem.flatNumber = flatNumber
newWorkItem.propertyName = propertyName
newWorkItem.propertyNumber = propertyNumber
newWorkItem.street = street
newWorkItem.locality = locality
newWorkItem.town = town
newWorkItem.postcode = postcode
return newWorkItem
这是我目前用来解析 json 并创建新记录的代码:
if let moc = self.managedObjectContext
moc.performBlockAndWait(
Work.createInManagedObjectContext(moc,
id: object["Id"].stringValue,
flatNumber: object["FlatNumber"].stringValue,
propertyName: object["PropertyName"].stringValue,
propertyNumber: object["PropertyNumber"].stringValue,
street: object["Street"].stringValue,
locality: object["Locality"].stringValue,
town: object["Town"].stringValue,
postcode: object["Postcode"].stringValue,
createdDate: object["CreatedDate"].stringValue
)
for party in object["Parties"].arrayValue
Party.createInManagedObjectContext(moc,
id: party["Id"].stringValue,
firstName: party["FirstName"].stringValue,
lastName: party["LastName"].stringValue,
propertyName: party["PropertyName"].stringValue,
propertyNumber: party["PropertyNumber"].stringValue,
street: party["Street"].stringValue,
locality: party["Locality"].stringValue,
town: party["Town"].stringValue,
postcode: party["Postcode"].stringValue,
createdDate: party["CreatedDate"].stringValue)
// println(object["Parties"])
)
moc.save(nil)
现在我知道这不是进行这种操作的最佳方式,老实说,这个模式会很大,其他实体中会有很多记录依赖于这个 Work 实体。
我想我会从各方开始,因为可能有很多方,但我不确定如何将每一方与工作实体联系起来。我确实尝试过传入 workId,并认为也许我需要将 Work 对象传回 Work 托管对象,但我很肯定有比拥有诸如此类的庞大函数更好的方法吗?
所以我的问题是,在这种情况下,处理创建具有多个关系的实体的最佳方法是什么?
更新:
我已将实现更改如下:
让 work = NSEntityDescription.insertNewObjectForEntityForName("Work", inManagedObjectContext: moc) as!工作
let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"
work.id = object["Id"].stringValue
work.flatNumber = object["FlatNumber"].stringValue
work.propertyName = object["PropertyName"].stringValue
work.propertyNumber = object["PropertyNumber"].stringValue
work.street = object["Street"].stringValue
work.locality = object["Locality"].stringValue
work.town = object["Town"].stringValue
work.postcode = object["Postcode"].stringValue
work.createdDate = formatter.dateFromString(object["CreatedDate"].stringValue)!
for obj in object["Parties"].arrayValue
let party = NSEntityDescription.insertNewObjectForEntityForName("Party", inManagedObjectContext: moc) as! Party
party.id = obj["Id"].stringValue
party.firstName = obj["FirstName"].stringValue
party.lastName = obj["LastName"].stringValue
party.propertyName = obj["PropertyName"].stringValue
party.propertyNumber = obj["PropertyNumber"].stringValue
party.street = obj["Street"].stringValue
party.locality = obj["Locality"].stringValue
party.town = obj["Town"].stringValue
party.postcode = obj["Postcode"].stringValue
party.createdDate = formatter.dateFromString(obj["CreatedDate"].stringValue)!
//doesn't work
work.parties.addlistObject(party)
我确实尝试过实现下面描述的 NSSet 解决方案,但遇到了当前循环在我的 JSON 上迭代的问题
编辑:
我已经设法通过添加来让它工作
party.work = work as Work
在下面建议的 for 循环内。
现在它运行了一段时间并且似乎在做正确的事情,直到它因错误而崩溃:
fatal error: unexpectedly found nil while unwrapping an Optional value
这是一个单独的问题还是相关的问题?
【问题讨论】:
该错误消息仅表示有一个值为 nil,但其变量不是可选的(即:testVar 或 testVar!而不是 testVar?)。发生错误时,您能否将错误日志或调试面板的照片发布到左侧?您通常可以追溯错误以查看调用了哪些方法以及错误发生在代码的哪一行。 啊,谢谢,我解决了,以后我需要检查我所有的 JSON 是否有任何空值 欢迎您。祝你的项目好运! 【参考方案1】:使用 Core Data,您尝试做的事情实际上非常简单。您要求的是一种将两个实体彼此连接在一起的方法。
现在,您似乎希望在一个工作实体下拥有多个参与方。这意味着您正在查看 Work 实体和 Party 实体之间的 To-Many 关系。您需要做的就是在两个实体之间创建如下所示的关系:
首先,在“Relationships”标签下找到您的 Work 实体,然后点击“+”按钮。将此新关系命名为“parties”,然后单击 Enter。将目的地设为您的缔约方实体。
其次,转到您的当事方实体并执行相同操作,将关系命名为“work”并将其目的地设置为您的 Work 实体。但是这一次,单击“反向”下的下拉菜单并选择您的各方关系以在您的工作和各方实体之间形成一对一的关系。现在,您的 Work 实体的每个实例都包含一个变量,该变量包含一个相对方实体的实例,反之亦然。
但是,您可能希望“Parties”实体的多个实例将您连接到一个 Work 实例,因此现在您希望将关系更改为 To-Many 关系。我们可以通过转到您的工作实体并单击“各方”关系来做到这一点。现在,在右侧的 Data Model Inspector 中,查找显示“Type”的菜单。单击菜单并从下拉列表中选择“To Many”。
您现在在实体之间建立了多对多关系!
现在,要在代码中添加连接,请打开您的 Party.swift 文件,然后在底部键入:
@NSManaged var work: Work
这给出了该方连接到的工作对象的引用。您可以在for party in object["Parties"].arrayValue ...
中创建您的派对实例时进行设置。只需使用
party.work = Your Work instance
但是,对于 Work 类,情况略有不同。你看,我们建立关系的方式,当事人实体只能在一个工作实体下,但工作实体可以包含多个当事人。 Core Data 会将这些存储为 NSSet(或 NSOrderedSet,如果您想对集合中的 Party 对象进行排序)。所以将这段代码添加到 Work.swift 的底部:
@NSManaged var parties: NSSet
这将创建一个 NSSet 实例,该实例将包含 Work 实例下的所有当事方。现在,您可以通过创建一个新的 NSSet 实例并将其分配给party 变量来添加派对,如下所示:
let newSet = NSMutableSet(setWithSet: parties)
newSet.addObject(party variable)
myWork.parties = newSet.copy() as! NSSet
然后,如果您有工作 ID,则可以使用 myParty.work.workID == "SomeWorkID"
检查 ID。如果需要,还可以通过各方 NSSet 进行枚举。
希望这个答案可以帮助您完成您想要完成的工作!如果这不能完全回答您的问题,请告诉我。
如果你想对 CoreData 关系做更多的研究,你可以得到一本关于 Core Data 的书(我买了 Ray Wenderlich 的“Core Data by Tutorials”)或查看 Apple 的文档here。
【讨论】:
我在建立关系时仍然遇到问题,请查看我的更新以上是关于Swift 核心数据关系和种子数据的主要内容,如果未能解决你的问题,请参考以下文章