How can I properly copy objects from one Realm object to another object

社会主义新天地 提交于 2019-12-24 06:29:34

问题


Based on the following code I would like to be able to create a new ItemList from an existing one. In other words I have an ItemList called First List and I want to create a new ItemList, call it Second List and fill it with the Items from First List.

The way I have it right now is that it creates the Second List as expected, the Items from the First List show in Second List but what doesn't work is when I want to delete only the Items from First List, it deletes Items from both lists. I guess I'm not truly copying the items.

So the question is, how can I copy Items from First List to Second List?

Object Models:

class ItemList: Object {
    dynamic var listName = ""
    dynamic var createdAt = NSDate()
    let items = List<Item>()
}

class Item:Object{
    dynamic var productName:String = ""
    dynamic var createdAt = NSDate()
}

Code to create Second List from First List

This Works fine, it creates Second List and adds the items from First List but I don't think I'm making copies just showing them in Second List.

        let newList = ItemList()
        newList.listName = "Second List"

        if let selectedList = realm.objects(ItemList.self).filter("listName = %@", "First List").first{
            let itemsFromFirstList = selectedList.items
            newList.items.append(objectsIn:itemsFromFirstList)
        }

        try! realm.write {
            realm.add(newList)
        }

This code is supposed to delete only the items from First List

This actually deletes items from both First List and Second List

    let listToDelete = realm.objects(ItemList.self).filter("listName = %@", "First List").first

    try! realm.write {
        for item in (listToDelete?.items)! {
            realm.delete(realm.objects(Item.self).filter("productName = %@", item.productName).first!)

        }
    }

回答1:


What you want to do is use:

for record in postsDB.objects(PostModel.self) {
    if !combinedDB.objects(PostModel.self).filter("postId == \(record.parentId)").isEmpty {
          combinedDB.create(PostModel.self, value: record, update: false)
    }
}

The create method is inherited from Object. It tells the target to create a new object. Use true if you want it to look to see if there is already a record there, and update it if there is. PostModel is the Object type, record is what you want copied.

Edit: I added the if statement to provide more context. You didn't show your class definitions, so I was guessing. This is a working example. I ask for a set of records from DatabaseA and copy it to DatabaseB (postsDB to combinedDB).

So if the type of the object you're trying to insert is a List, I'd recommend you define a subclass of Object, and have at least the list you need as a property.

class TagList: Object {
    dynamic var tag = ""
    var list = List<PostModel>()

    override class func primaryKey() -> String? {
        return "tag"
    }
}

Full working example illustrating: creating new objects, copying all objects to a second list, deleting from second list after copying, adding to first list (which didn't get anything deleted from it.

import Foundation
import RealmSwift

class Letter: Object {
    dynamic var letter = "a"
}

class Letters: Object {
    var letterList = List<Letter>()
}

class ListExample {
    let listRealmStore = try! Realm() // swiftlint:disable:this force_try

    func testThis() {
        print(Realm.Configuration.defaultConfiguration.fileURL!)
        listRealmStore.beginWrite()
        addSingleItems()  // add 3 objects to the DB

        let firstList = Letters()
        let allObjects = listRealmStore.objects(Letter.self)
        for item in allObjects {
            firstList.letterList.append(item)
        }

        let secondList = Letters()
        let itemsToCopy = firstList.letterList
        for item in itemsToCopy {
            let obj = listRealmStore.create(Letter.self)
            obj.letter = item.letter
            secondList.letterList.append(obj)
        }

        let third = Letter()
        third.letter = "Z"
        listRealmStore.add(third)

        firstList.letterList.append(third)
        secondList.letterList.removeLast()
        do {
            try listRealmStore.commitWrite()
        } catch let error {
            print("couldn't commit db writes: \(error.localizedDescription)")
        }

        print("list one:\n\(firstList)")
        print("list two:\n\(secondList)")
    }

    func addSingleItems() {

        for letter in ["a", "b", "c"] {
            let objectToInsert = Letter()
            objectToInsert.letter = letter
            listRealmStore.add(objectToInsert)
        }
    }
}

Results in:

list one:
Letters {
    letterList = List<Letter> (
        [0] Letter {
            letter = a;
        },
        [1] Letter {
            letter = b;
        },
        [2] Letter {
            letter = c;
        },
        [3] Letter {
            letter = Z;
        }
    );
}
list two:
Letters {
    letterList = List<Letter> (
        [0] Letter {
            letter = a;
        },
        [1] Letter {
            letter = b;
        }
    );
}



回答2:


Are you really trying to create copies of your items, or do you just want to be able to remove them from lists independently?

When you do:

newList.items.append(objectsIn: itemsFromFirstList)

you end up with the same objects being in both lists. List<T> just stores references to objects that live within the Realm. Appending an object to a List just references the existing object, it doesn't copy the object.

When you call Realm.delete(_:) you remove that object entirely from the Realm, not just from a single list that it is a member of. To remove an object from a List, you should instead use List.remove(objectAtIndex:).



来源:https://stackoverflow.com/questions/43728643/how-can-i-properly-copy-objects-from-one-realm-object-to-another-object

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!