Lory Huz Lory Huz - 1 year ago 41
Swift Question

Realm: Create new instances of User is removing stored lists of other User instances

In my User model I store some list like this:

public final class User: Object, Mappable {

dynamic var id: Int = 0
dynamic var name: String? = nil
var addresses = List<Address>()
var children = List<Child>()
var godparents = List<User>()
}


I save the user with the id 1 in Realm, with some addresses and children, it's working great and it's persisted after the app is killed.

But when I want to create totally new users, for example user with ids 2 & 3, the user with id 1 will lost all list data (name will be still persisted, but all addresses or children are lost). What's wrong here ?

Here is the code where I want to add users 2 & 3 in godparents list of user 1:

do {
try realm.write {
// users contains user 2 & 3
let users = self.users.map { (userData) -> User in
return realm.create(User.self, value: userData, update: true)
}

UserManager.currentUser?.godparents.removeAll()
UserManager.currentUser?.godparents.append(contentsOf: users)
}
} catch let error {
print(error) // no error is triggered at this point
}


After this code is executed, user 1 lost all data in addresses & children

Here is a code of currentUser method if needed (to get user id 1):

struct UserManager {
static var currentUser: User? {
get {
guard let id = UserDefaults.standard.object(forKey: "current_user_id") else {
return nil
}

let user = realm?.object(ofType: User.self, forPrimaryKey: id)
return user
}
}
}

TiM TiM
Answer Source

When you use realm.create() with update: true, you need to be very careful what you pass to it. Realm doesn't treat present, but empty values as 'do not touch', it instead assumes you wanted to nil out that value.

Assuming userData is just a standard dictionary, you should only pass the values you want to change, and (ideally) omit any values that don't change.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download