使用Swift 3向Realm添加数组

13

我是Realm的新手,我尝试像操作字符串一样添加一个数组,但最终出现了一些错误。经过一番搜索后,我找到了解决方案:

class Sensors : Object {


    dynamic var name = ""
    dynamic var message = ""

    var topic: [String] {
        get {
            return _backingNickNames.map { $0.stringValue }
        }
        set {
            _backingNickNames.removeAll()
            _backingNickNames.append(objectsIn: newValue.map({ RealmString(value: [$0]) }))
        }
    }
    let _backingNickNames = List<RealmString>()

    override static func ignoredProperties() -> [String] {
        return ["topic"]
    }




}

class RealmString: Object {
    dynamic var stringValue = ""
}

这个工作得非常好,现在我想在这个类中添加另一个数组。 如果有人知道使用 realm 添加数组的其他方法,请分享一下。

提前感谢您


使用List的问题是什么? - Horst
我说过了,我是新手,我不知道所有的选项。 - mike vorisis
3个回答

23
作为一般规则,使用Realm提供的一对多关系比尝试使用数组模拟它们更加高效(Realm的集合是惰性的,仅在需要时才实例化其中包含的对象,而不是普通的Swift数组)。
在您的情况下,如果我正确理解您要做什么,您想将[RealmString] Swift数组添加到_backingNickNames列表中。
为什么不使用Realm的List类的append(objectsIn:)方法(请参见here),像这样:
// Dog model
class Dog: Object {
    dynamic var name = ""
    dynamic var owner: Person?
}

// Person model
class Person: Object {
    dynamic var name = ""
    dynamic var birthdate = NSDate(timeIntervalSince1970: 1)

    let dogs = List<Dog>()
}

let jim = Person()

let dog1 = Dog()
let dog2 = Dog()

// here is where the magic happens
jim.dogs.append(objectsIn: [dog1, dog2])

如果你想要做相反的事情(将List转换为Array),只需执行以下操作:
let dogsArray = Array(jim.dogs)

• • • • • • • •

回到您自己发布的解决方案,您可以轻松地重构模型以适应此需求。每个Sensor对象可以附加多个Topic和多个Message对象。

只需放弃messagetopic计算属性,并将topicVmessageV重命名为topicsmessages,同时将RealmString重命名为Topic,将RealmString1重命名为Message

现在,您可以轻松地遍历附加到传感器上的主题,例如:

for topic in sensor1.topics { ... }

如果你想将消息附加到传感器,可以像这样操作(不要忘记先正确添加新创建的对象到数据库中):

let message1 = Message()
message1.stringValue = "Some text"

sensor2.messages.append(message1)

因此,无需使用中间的 Swift 数组。

谢谢您的回答,我会检查一下看看这是否是我想要的。 - mike vorisis
@mikevorisis:只是好奇这是否对你有所帮助。 - Bogdan Farca
实际上,在进行一些搜索和测试后,我终于明白了这是如何工作的,并且我发现你的方法比我的更容易,所以我将把你的问题标记为最佳答案!再次感谢你! - mike vorisis

1

经过测试,我成功添加了另一个类似于这样的数组:

class Sensors : Object {


    dynamic var type = ""
    dynamic var name = ""
    dynamic var badge = 0

    var topic: [String] {
        get {
            return topicV.map { $0.stringValue }
        }
        set {
            topicV.removeAll()
            topicV.append(objectsIn: newValue.map({ RealmString(value: [$0]) }))
        }
    }

    var message: [String] {
        get {
            return messageV.map { $0.stringValue1 }
        }
        set {
            messageV.removeAll()
            messageV.append(objectsIn: newValue.map({ RealmString1(value: [$0]) }))
        }
    }





    let topicV = List<RealmString>()
    let messageV = List<RealmString1>()

    override static func ignoredProperties() -> [String] {
        return ["topic", "message"]
    }




}

class RealmString: Object {
    dynamic var stringValue = ""
}

class RealmString1: Object {
    dynamic var stringValue1 = ""
}

Mike,你为什么要在Realm列表和Swift数组之间来回转换呢?这样非常低效,并且在你的代码中增加了不必要的复杂性。 - Bogdan Farca
我不明白如何使用其他方法。 - mike vorisis
我已经更新了我的答案,展示了一种可能的方式来正确地重构您的代码,以便在模型中利用完整的 Realm 对象和关系。 - Bogdan Farca

0

bogdanf所说的以及您实现的方式都是正确的。

除了基本值类型之外,Realm只能存储对单个Realm Object对象的引用,以及使用List类型的Object数组。因此,如果要保存一组类型,必须将您想要保存的任何基本类型(例如这里的String)封装在方便的Realm Object中。

像bogdanf所说的那样,不建议将Realm List转换为标准Swift数组,然后再转回来,因为您会失去Realm的惰性加载功能的优势(这可能会导致性能和内存问题),但是可以通过将从Realm复制数据的代码封装在@autoreleasepool块中来缓解内存问题。

class MyObject: Object {
    dynamic var childObject: MyObject?
    let objectList = List<MyObject>()
}

所以回顾一下,在可能的情况下最好直接使用 Realm 的 List 对象进行工作,并在实际需要遍历 Realm 中每个子对象的时候使用 @autoreleasepool。 :)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接