XiOS
XiOS

Reputation: 1795

Realm swift adding object to list fails

I am trying to persist a list of ObjectB is ObjectA, where adding ObjectA to list fails and making the whole write transaction fail. The code as below,

public final class User: Object {
    @Persisted(primaryKey: true) public var userObjectId: ObjectId
    .......
    @Persisted public var assignments: List<Assignment>
    .......
}

public final class Assignment: Object {
    @Persisted(primaryKey: true) public var assignmentObjectId: ObjectId
    @Persisted public var name: String?
}

With the above models, I try to do the below to create an assignment and add the created assignment to the user's assignments list,

func createAssignentForUser(_ user: User) {
    do {
        let realm = Realm()
        try realm.write { 
            let assignment = Assignment(name: "ass_name")
            realm.add(assignment)
            user.assignments.append(assignment) //something feels wrong here.
        }
    } catch {
        // handle error
    }
}

If I put a debug pointer and query user.assignments.count, I can see the count as 1 when the corresponding line is executed. But when I open the Database to see the inserted objects,I neither see any entry created for Assignment entity, nor any assignment added to user's assignments list. Both are zero. The above code doesn't throw any error either.

Now, if I remove the line user.assignments.append(assignment) from the above code, then it does create an entry in the Assignment entity.

With this line present, it doesn't seem to create the assignment itself, i.e, the line realm.add(assignment) itself doesn't seem to work.

So what is wrong with the above code? Isn't above the correct way of adding created object to a list ?

Upvotes: 1

Views: 180

Answers (1)

Jay
Jay

Reputation: 35648

There are a number of things to correct but in general, the code will be ok with a minor tweak or two and a bit of backing information:

First, avoid Realm and Swift collisions; a List is also a SwiftUI object and that can cause compiler confusion. Change the List in this

@Persisted public var assignments: List<Assignment>

to this

@Persisted public var assignments: RealmSwift.List<Assignment> //added RealmSwift

Second, the public var can just be var.

public var userObjectId: ObjectId

Next, this should not work or even compile (it throws a compiler error for me Incorrect argument label in call (have 'name:', expected 'value:')

let assignment = Assignment(name: "ass_name")

...as that's how to compose a Struct. In Realm we use classes and you'll need a convenience init in your Realm object

public final class Assignment: Object {
    @Persisted(primaryKey: true) public var assignmentObjectId: ObjectId
    @Persisted public var name: String?

    convenience init(name: String) {
        self.init()
        self.name = name
    }
}

Lastly, where you noted this

//something feels wrong here

There's actually nothing wrong - but it is redundant.

realm.add(assignment)

persists the assignment object; but Realm is pretty smart - if an object does not exist but needs to, it will also persist the assignment object here

user.assignments.append(assignment)

And will also add the assignment object to the assignments List.

Upvotes: 0

Related Questions