web-dev-qa-db-ja.com

Swift 3でレルムに配列を追加します

私は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 = ""
}

これは非常にうまく機能しているので、このクラス内に別の配列を追加したいと思います。レルムで配列を追加する他の方法を誰かが知っている場合は、それを共有してください。

前もって感謝します

10
mike vorisis

一般的な規則として、配列を使用してそれらをエミュレートしようとする代わりに、Realmによって提供される1対多の関係を使用する方が効率的です(Realmのコレクションは遅延であり、含まれるオブジェクトは、プレーンSwift配列)。

あなたの場合、あなたが何をしようとしているのかを私が正しく理解しているなら、_[RealmString]_リストに__backingNickNames_ Swift配列を追加する必要があります。

次のように、レルムの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])
_

反対のことをしたい場合(リストから配列に変換)は次のようにします:

_let dogsArray = Array(jim.dogs)
_

••••••••

独自の投稿されたソリューション に戻ると、これに対応するためにモデルを簡単にリファクタリングできます。各Sensorオブジェクトには、いくつかのTopicおよびいくつかのMessageオブジェクトをアタッチできます。

messagetopicの計算済みプロパティを破棄し、topicVmessageVの名前をそれぞれtopicsmessagesに変更します。また、RealmStringTopicに、_RealmString1_をMessageに名前変更します。

これで、たとえば次のようなセンサーに接続されたトピックを簡単に反復できます。

_for topic in sensor1.topics { ... }
_

または、センサーにメッセージを添付する場合は、次のようなことを実行できます(最初にDBに新しく作成したオブジェクトを 適切に追加 することを忘れないでください)。

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

sensor2.messages.append(message1)
_

したがって、中間のSwift配列を使用する必要はありません。

19
Bogdan Farca

テストした後、そのような別の配列を追加することができました。

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 = ""
}
1
mike vorisis

Bogdanfの発言と、それを実装した方法はどちらも正しいです。

基本的な値タイプは別として、Realmは、単一のRealm Objectオブジェクトへの参照と、Objectタイプを使用するListsの配列のみを格納できます。そのため、型の配列を保存する場合は、保存する基本的な型(ここではStringなど)を便利なレルムObjectにカプセル化する必要があります。

Bogdanfが言ったように、Realmの遅延読み込み機能(両方のパフォーマンスを引き起こす可能性がある)の利点を失うので、Realm Listsを標準のSwift配列に変換して再度戻すことはお勧めしません。およびメモリの問題)が、レルムからデータをコピーするコードを@autoreleasepoolブロックで囲むことにより、メモリの問題を少なくとも軽減できます。

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

したがって、レビューでは、可能な限りRealm Listオブジェクトを直接操作し、Realm内のすべての子オブジェクトを実際にループしたい場合はいつでも@autoreleasepoolを使用することをお勧めします。 :)

0
TiM