1

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 です...したがって、グローバルに一意です。

4

2 に答える 2

0

あなたの問題はおそらくMessage(json:)初期化子にあります。メッセージの JSON を処理すると、作成者 ID (およびおそらく残りの作成者データ) が渡されると思います。イニシャライザでは、Realm 内の既存の User のインスタンスを取得するのではなく、おそらく新しい User をインスタンス化しています。モデル オブジェクトを再作成し、既存のユーザー、スレッド、およびメッセージを作成しました。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()
于 2014-10-23T17:48:16.473 に答える