The Notorious Object already managed by another realm

I have come across this topic in a few searched but still not sure how to make it work. After upgrading from previous RealmSwift SDK to 10.x I now get this " Object already managed…" error. I know it is nested objects or relations causing it but I am not sure how to make it work until this bug is fixed.

Basically, if you are trying to insert or upsert a docuemnt that has a nested objectId it throws this error. Below is some code that I can share that causes the error. I have a user, club, and game model. When creating a new game that has an ObjectId field and an array of ObjectIds, realmSwift requires those model be the model of that particular object itself. For example

class User: Object, ObjectKeyIdentifiable {
    @Persisted(primaryKey: true) var _id: ObjectId
    @Persisted var _partition: String = "partition"
    @Persisted var clubId: Club?
    @Persisted var fullName: String = ""
    ...
}

This is a user class that in the database just houses the objectId that related to the club but realmswift requires it to be the club model. this worked fine up until SDK 10.x but now it wont let me write a user to the realm unless i do not include the club nested object. So, this causes many problems as my app revolves around creating new games and has 2-3 nested objects or arrays of objects. Below is some sample of that code that I can share, slightly altered but should give a general idea of what I am dealing with. Any help to work around this until it is fixed is greatly appreciated.

Models:

class User: Object, ObjectKeyIdentifiable {
    @Persisted(primaryKey: true) var _id: ObjectId
    @Persisted var _partition: String = "partition"
    @Persisted var clubId: Club?
    @Persisted var fullName: String = ""
    ...
}

Class Club Object, ObjectKeyIdentifiable {
    @Persisted(primaryKey: true) var _id: ObjectId
    @Persisted var _partition: String = "partition"
    @Persisted var clubId: Club?
    @Persisted var name: String = ""
    ...
}

Class Game Object, ObjectKeyIdentifiable {
    @Persisted(primaryKey: true) var _id: ObjectId
    @Persisted var _partition: String = "partition"
    @Persisted var clubId: Club?
    @Persisted var hostId: User?
    @Persisted var users: RealmSwift.List<User>
    ...
}

Data:

Game:
{
  "_id": { "$oid": "660064c69a7c4bed68509f90" },
  "_partition": “partition”,
  "clubId": {
    "$oid": "5ef944d846779f3aef97c5fb"
  },
  "hostId": {
    "$oid": "6365894c7998127adaa7dde0"
  },
  “users”: [
    { "$oid": "660169d6c7241ef4e01d9c94" },
    { "$oid": "608e01d21e6d9297988a1838" },
    { "$oid": "6365894c7998127adaa7dde0" }
  ]
}

User1:
{
  "_id": { "$oid": "660169d6c7241ef4e01d9c94" },
  "_partition": "partition",
  "clubId": {
    "$oid": "5ef944d846779f3aef97c5fb"
  },
  "fullName": "Joe"
}

User2:
{
  "_id": { "$oid": "608e01d21e6d9297988a1838" },
  "_partition": "partition",
  "clubId": {
    "$oid": "5ef944d846779f3aef97c5fb"
  },
  "fullName": "Fred"
}

User3:
{
  "_id": { "$oid": "6365894c7998127adaa7dde0" },
  "_partition": "partition",
  "clubId": {
    "$oid": "5ef944d846779f3aef97c5fb"
  },
  "fullName": "Bob"
}

User4:
{
  "_id": { "$oid": "6086f0783b7450f676b81a9d" },
  "_partition": "partition",
  "clubId": {
    "$oid": "5ef944d846779f3aef97c5fb"
  },
  "fullName": "Tom"
}

Club:
{
  "_id": { "$oid": "6601696bc7241ef4e01d9c93" },
  "_partition": "partition",
  "name": "The Only Club"
}

struct CreateMatch: View {
    @EnvironmentObject var state: AppState
    @Environment(\.dismiss) var dismiss
    @State private var selectedDateTime = Date.now
    @State private var isPublic = false
    @State private var minRating = 2.5
    @State private var maxRating = 7.0
    private var newGame = Game()
    @Binding private var users: [User]
    var gameUsers: RealmSwift.List<User> = RealmSwift.List<User>()
    var clearMatchUsers = {}
    
    @State private var showNotFullAlert = false
    
    init(users: Binding<[User]>) {
        self._users = users
        gameUsers.append(objectsIn: self.users)
        UIDatePicker.appearance().minuteInterval = 15
        UISegmentedControl.appearance().selectedSegmentTintColor = UIColor(Color.theme.tennisCourtGreen)
    }
        
    var body: some View {
        ZStack{
            ScrollView {
                VStack {
                    ...  shows some pickers and boxes to change data.  View works fine, it's just a problem when writing to realm.
                    }
                }
         ...
    }
}

extension CreateGame {
    
    private func handleLetsPlay() {
        createNewGame)
    }
    
    private func createNewGame() {
        newGame.gameDate = selectedDateTime
        newGame.gameDate.users = gameUsers
        newGame.gameDate.hostId = state.user
        newGame.gameDate.clubId = state.user.clubId
        
        state.writeToRealm(newGame)
    }
}

class AppState: ObservableObject {
    var loginPublisher = PassthroughSubject<RealmSwift.User, Error>()
    var logoutPublisher = PassthroughSubject<Void, Error>()
    let userRealmPublisher = PassthroughSubject<Realm, Error>()
    var cancellables = Set<AnyCancellable>()
    
    @StateObject var locationManager = LocationDataManager()
    
    @Published var shouldIndicateActivity = false
    @Published var isLoggingIn = false
    @Published var error: String?    
    
    @Published var user: User = User()
    @Published var realm: Realm?
    
    var loggedIn: Bool {
        app.currentUser != nil && app.currentUser?.state == .loggedIn
    }
            
    init() {
        logoutPublisher
            .receive(on: DispatchQueue.main)
            .sink(receiveCompletion: { _ in
            }, receiveValue: { _ in
                self.user = User()
            })
            .store(in: &cancellables)
    }
    
    func openRealm(user: RealmSwift.User) {
        let realmConfig = user.configuration(partitionValue: Constants.REALM_PARTITION_VALUE)
        let predicate = NSPredicate(format: "userId == %@", app.currentUser?.id ?? "")
        Realm.Configuration.defaultConfiguration = realmConfig
        Realm.asyncOpen(configuration: realmConfig) { result in
            switch result {
            case .failure(let error):
                self.isLoggingIn = false
                self.error = "Failed to open realm: \(error.localizedDescription)"
                return
                
            case .success(let realm):
                self.realm = realm
                if let newUser = realm.objects(User.self).filter(predicate).first {
                    self.user = newUser
                    self.isLoggingIn = false
                } else {
                    do {
                        try realm.write {
                            let user = User()
                            user.fullName = ""
                            user.email = ""
                            user._partition = Constants.REALM_PARTITION_VALUE
                            user.userId = app.currentUser?.id ?? ""
                            realm.add(user, update: .modified)
                            self.isLoggingIn = false
                        }
                    } catch {
                        self.isLoggingIn = false
                        self.error = " Could not add user to Realm"
                    }
                }
            }
        }
    }
    
    func writeToRealm(_ object: RealmSwift.Object) {
        shouldIndicateActivity = true
        if let realm = self.realm {
            do {
                try realm.write {
                    realm.add(object, update: .modified)
                }
                shouldIndicateActivity = false
            } catch {
                self.isLoggingIn = false
                self.error = " Could not add data to Realm"
                shouldIndicateActivity = false
            }
        }
    }
        
}

Of course after all the days of troubleshooting and searching, I figure it out after I posted.

I changed my writeToRealm function to be a create with .modified instead of add

Old function

func writeToRealm(_ object: RealmSwift.Object) {
        shouldIndicateActivity = true
        if let realm = self.realm {
            do {
                try realm.write {
                    realm.add(object, update: .modified)
                }
                shouldIndicateActivity = false
            } catch {
                self.isLoggingIn = false
                self.error = " Could not add data to Realm"
                shouldIndicateActivity = false
            }
        }
    }

New Function

    func writeToRealm(_ object: RealmSwift.Object, type: RealmSwift.Object.Type) {
        shouldIndicateActivity = true
        if let realm = self.realm {
            do {
                try realm.write {
                    realm.create(type, value: object, update: .modified)
                }
                shouldIndicateActivity = false
            } catch {
                self.isLoggingIn = false
                self.error = " Could not add data to Realm"
                shouldIndicateActivity = false
            }
        }
    }

Just have to specify object.type on the call now.

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.