【问题标题】:Weird behavior when copying objects in Realm在 Realm 中复制对象时的奇怪行为
【发布时间】:2017-05-03 14:22:48
【问题描述】:

以下代码通过从名为 First List 的现有 ItemList 复制 Items 创建一个名为 Second List 的新 ItemList。创建Second List 后,我想从First List 中删除所有Items,我的问题是,由于某种原因,当我调用deleteItemsFromFirstList() 方法从第一个列表中删除项目时,最后一个Item 来自@ 987654331@ 被删除并移至Fist List 所以,我最终在First List 中得到一(1)个Item,最后一个Item 在Second List 中丢失。理论上Second List 应该包含所有三 (3) 项,First List 应该为空。我希望这是有道理的。

我做错了什么?

编辑: 我想要做的是将项目从第一个列表复制到第二个列表,然后从第一个列表中删除项目,但在领域中保留第一个列表(空)。

代码如下:

领域对象模型

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

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

添加和删除方法

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

    if let firstList = realm.objects(ItemList.self).filter("listName = %@", "First List").first{
        let itemsFromFirstList = firstList.items

        try! realm.write {
            for i in itemsFromFirstList{
                let obj = realm.create(Item.self)
                obj.basePrice = i.basePrice
                obj.productName = i.productName
                newList.items.append(obj)
                realm.add(newList)
            }
        }
    }
}

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

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

输出

现有列表:这就是First List 的样子(未显示创建它的代码)

Results<ItemList> (
    [0] ItemList {
        listName = First List;
        createdAt = 2017-05-03 01:32:45 +0000;
        items = RLMArray <0x6100000f4100> (
            [0] Item {
                basePrice = 1;
                productName = Apples;
                createdAt = 2017-05-03 01:32:57 +0000;
            },
            [1] Item {
                basePrice = 2;
                productName = Oranges;
                createdAt = 2017-05-03 01:33:04 +0000;
            },
            [2] Item {
                basePrice = 3;
                productName = Bananas;
                createdAt = 2017-05-03 01:33:13 +0000;
            }
        );
    }
)

Second List 创建后。此时,两个列表看起来相同,这正是我想要的。

Results<ItemList> (
    [0] ItemList {
        listName = First List;
        createdAt = 2017-05-03 01:32:45 +0000;
        items = RLMArray <0x6080000f5680> (
            [0] Item {
                basePrice = 1;
                productName = Apples;
                createdAt = 2017-05-03 01:32:57 +0000;
            },
            [1] Item {
                basePrice = 2;
                productName = Oranges;
                createdAt = 2017-05-03 01:33:04 +0000;
            },
            [2] Item {
                basePrice = 3;
                productName = Bananas;
                createdAt = 2017-05-03 01:33:13 +0000;
            }
        );
    },
    [1] ItemList {
        listName = Second List;
        createdAt = 2017-05-03 01:34:03 +0000;
        items = RLMArray <0x6080000f5b00> (
            [0] Item {
                basePrice = 1;
                productName = Apples;
                createdAt = 2017-05-03 01:34:03 +0000;
            },
            [1] Item {
                basePrice = 2;
                productName = Oranges;
                createdAt = 2017-05-03 01:34:03 +0000;
            },
            [2] Item {
                basePrice = 3;
                productName = Bananas;
                createdAt = 2017-05-03 01:34:03 +0000;
            }
        );
    }
)

调用deleteItemsFromFirstList() 方法后。请注意,在此调用之前,两个列表都有三 (3) 个 Items,但现在 Second List 只有两个,First List 最终只有一 (1) 个。理论上,Second List 应该包含所有三 (3) 项,First List 应该为空。

Results<ItemList> (
    [0] ItemList {
        listName = First List;
        createdAt = 2017-05-03 01:32:45 +0000;
        items = RLMArray <0x6100000f1f00> (
            [0] Item {
                basePrice = 3;
                productName = Bananas;
                createdAt = 2017-05-03 01:33:13 +0000;
            }
        );
    },
    [1] ItemList {
        listName = Second List;
        createdAt = 2017-05-03 01:34:03 +0000;
        items = RLMArray <0x6100000f6400> (
            [0] Item {
                basePrice = 1;
                productName = Apples;
                createdAt = 2017-05-03 01:34:03 +0000;
            },
            [1] Item {
                basePrice = 2;
                productName = Oranges;
                createdAt = 2017-05-03 01:34:03 +0000;
            }
        );
    }
)

知道我做错了什么吗?

【问题讨论】:

    标签: ios swift realm


    【解决方案1】:

    您不应该尝试删除这些项目,因为当您将它们添加到列表中时,您实际上并没有在 Realm 中复制这些项目本身,您只是将这些项目的引用添加到您的第二个列表中。

    首先,您应该明确您真正想要实现的目标。如果要删除第一个列表,而不是其中的项目,请从 Realm 中删除 ItemList 对象,而不是 ItemList.list 中的 Item 对象。

    如果您真的想从 Realm 中删除对象,您不能只过滤它们的名称,因为两个列表中的名称相同,您必须过滤例如 createdAt 属性。如果你选择这种方法,你应该将每个项目的 createdAt 属性更改为列表的相同属性,一旦你将它们添加到列表中,这样你就可以通过它进行过滤。

    【讨论】:

    • @ David Pasztor - 我想做的是将项目从第一个列表复制到第二个列表,然后从第一个列表中删除项目,但在领域中保留第一个列表(空)。我明白了你的观点(方法#3),出于某种原因,我以为我是在 Realm 中制作副本。快速提问。如果我理解这一点是正确的,那么您在方法#3 中的建议是在创建First List 中的引用之前更改First List 中所有项目的createdAt 属性,以便稍后我可以过滤和删除它们,更正?谢谢。
    • 除非您显式调用写入事务,否则自上次写入以来您创建/更改的任何 Realm 对象都不会保留在 Realm 中。您不能只在 Second List 中创建引用,您实际上需要在 First List 中创建所有项目的副本。对于这些副本, createdAt 属性应该是您复制它们的时间,并且您需要在将它们添加到 SecondList 之后添加它们。
    • 通过使用 deleteItemsFromFirstList method 中的 createdAt 属性似乎工作正常。谢谢。 realm.delete(realm.objects(Item.self).filter("createdAt = %@", i.createdAt).first!)
    猜你喜欢
    • 2015-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-13
    相关资源
    最近更新 更多