我有一个相当简单明了的问题,我试图用Realm来解决。我有对象具有数组属性(线程)。当我通过我们的API获取所有线程时,由于父对象被单独保存,因此它们全部持久存储到Realm中,因此数组属性中的所有子对象(消息和用户)也被正确保留。但是在应用程序的生命周期中,我需要将新消息添加到该数组属性中。这就是我试图做的事情:
func addPubNubMessageToThread(notification: NSNotification) {
if let info = notification.userInfo as? Dictionary<String, AnyObject> {
var embeddedMessage = Message(json: (info["data"] as? NSDictionary)!)
let threadId = (info["thread"]! as String)
// Persist the message to Realm for future use
var respectiveThread = Thread(forPrimaryKey: threadId)
let realm = RLMRealm.defaultRealm()
realm.beginWriteTransaction()
respectiveThread.conversation.insertObject(embeddedMessage, atIndex: UInt(0)) // Always fails here in XCode with the error below
realm.addOrUpdateObject(respectiveThread)
realm.commitWriteTransaction()
}
}
但每次我收到以下错误:
*** Terminating app due to uncaught exception 'RLMException', reason: 'Setting unique property '_id' with existing value '540729b543dd5d1868a42b5d''
有关更多背景信息,请参阅我的Realm模型:
class Message: RLMObject {
dynamic var _id = ""
dynamic var type = ""
dynamic var text = ""
dynamic var author = User()
dynamic var created = NSDate()
dynamic var lastUpdated = NSDate()
}
class Thread: RLMObject {
dynamic var _id = ""
dynamic var name = ""
dynamic var conversation = RLMArray(objectClassName: Message.className())
dynamic var participants = RLMArray(objectClassName: User.className())
dynamic var created = NSDate()
dynamic var lastUpdated = NSDate()
}
class User: RLMObject {
dynamic var _id = ""
dynamic var name = ""
dynamic var firstName = ""
dynamic var lastName = ""
dynamic var email = ""
dynamic var phone = ""
dynamic var username = ""
dynamic var avatar = NSData()
dynamic var created = NSDate()
dynamic var lastUpdated = NSDate()
}
每条消息都有一个名为author的属性,它所抱怨的_id
是消息作者(或用户对象)的_id
。错误消息很难破译。我认为它说我正在尝试使用已存在的主键创建新的用户对象。如果这是问题,我该怎么做才能将新的Realm对象添加到已经存在的对象的数组属性中?
修改
我正在为每个模型设置主键,如下所示:
override class func primaryKey() -> String {
return "_id"
}
_id
是MongoDB生成的GUID ...因此它是全球唯一的。
答案 0 :(得分:1)
问题是在打电话时
insertObject
您的对象和所有子对象都在Realm中创建,而不是在已存在的情况下更新。如果您首先显式更新您的对象(它也适用于所有子对象),那么这应该避免这个问题:
var persistedMessage = realm.addOrUpdateObject(embeddedMessage)
respectiveThread.conversation.insertObject(persistedMessage, atIndex: UInt(0))
答案 1 :(得分:0)
您的问题可能出在Message(json:)
初始化程序中。当您处理消息的JSON时,我猜测是否传递了作者ID(也许是作者数据的其余部分)。在初始化程序中,您可能实例化了一个新用户,而不是在领域中获取现有用户的实例。我重新创建了模型对象,然后创建了现有的用户,线程和消息。我能够从JSON反序列化消息并将新消息添加到现有会话数组中,只要我的反序列化逻辑抓住了现有用户(如果已提供)。这是我的示例初始化程序:
init(json : NSDictionary) {
self._id = json["_id"] as String
self.type = json["type"] as? String ?? ""
self.text = json["text"] as? String ?? ""
self.created = json["created"] as? NSDate ?? NSDate()
self.lastUpdated = json["lastUpdated"] as? NSDate ?? NSDate()
if let author = json["author"] as? NSDictionary {
if let authorId = author["_id"] as? String {
self.author = User(forPrimaryKey: authorId)
}
}
super.init()
}
在这种情况下,我的示例JSON:
{
"_id": "2",
"text": "new message",
"author": {"_id": "1"}
}
最后,读取JSON并添加到已保存线程的代码:
var error: NSError?
var jsonDictionary : NSDictionary!
if let dictionary = NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.allZeros, error: &error) as? NSDictionary {
jsonDictionary = dictionary
} else {
NSLog("\(error)")
return
}
let realm = RLMRealm.defaultRealm()
realm.beginWriteTransaction()
let newMessage = Message(json: jsonDictionary)
self.thread.conversation.addObject(newMessage)
realm.addOrUpdateObject(self.thread)
realm.commitWriteTransaction()