Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add arrays to Realm with swift 3

I'm new in Realm and I tried to add an Array as I did with strings and I ended up with some errors. So after a little search I found out a solution:

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

This is working very good, now I want to add another array inside this class. If someone knows any other ways to add arrays with realm please share it.

Thanks in advance

like image 717
mike vorisis Avatar asked Oct 27 '16 08:10

mike vorisis


2 Answers

As a general rule it's way more efficient to use the one-to-many relationships provided by Realm instead of trying to emulate them by using arrays (Realm's collections are lazy, the objects contained are instantiated only when needed as opposed to plain Swift arrays).

In your case, if I understand correctly what you're trying to do, you want to add [RealmString] Swift arrays to the _backingNickNames list.

Why not use the append(objectsIn:) method of Realm's List class (see here), like this:

// 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])

If you want to do the opposite (convert from a List to an Array) just do :

let dogsArray = Array(jim.dogs)

• • • • • • • •

Back to your own posted solution, you could easily refactor the model to accommodate this. Each Sensor object could have several Topic and several Message objects attached.

Just ditch the message and topic computed properties and rename topicV and messageV to topics and messages respectively. Also rename RealmString to Topic and RealmString1 to Message.

Now, you could easily iterate through the, say, topics attached to a sensor like this :

for topic in sensor1.topics { ... }

Or if you want to attach a message to a sensor you could do something like this (don't forget to properly add the newly created object to the DB first):

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

sensor2.messages.append(message1)

So, no need to use intermediary Swift Arrays.

like image 116
Bogdan Farca Avatar answered Nov 18 '22 04:11

Bogdan Farca


After testing I managed to add another array like that:

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 = ""
}
like image 24
mike vorisis Avatar answered Nov 18 '22 04:11

mike vorisis