Another "Object is managed by another realm" post (SwiftUI)

Hello! Thanks for reading. Some info:

  • I’ve seen other posts on this topic but I’m still having a hard time figuring out the flow of managed objects and why I’m getting this error.
  • I’m using a local-only database for now - plan to add syncing later.
  • I’m pretty new to Realm and SwiftUI, I’ve only been at it part-time for six months or so.
  • AssignedSkill, AssignedLearningPath are EmbeddedObjects, meant to exist within Student objects

Here’s my code. I’ve tried to make it obvious with the comments where the error is, look for the // ########### line.

struct AssignedLearningPathView: View {
    @ObservedRealmObject var student: Student
    @State var assignLearningPathIsPresented: Bool = false
    @Binding var refreshTrigger: Bool
    @Binding var path: NavigationPath

    var body: some View {
        FormHeader(text: "Learning Paths")
        
        Section {
            if !student.assignedLearningPaths.isEmpty {
                ForEach(student.assignedLearningPaths, id: \.self) { assignedLearningPath in
                    Text(assignedLearningPath.title)
                }
            } else {
                Button("Assign Learning Path") {
                    assignLearningPathIsPresented = true
                }
                .sheet(isPresented: $assignLearningPathIsPresented) {
                    NavigationStack {
                        AssignLearningPathScreen(onLearningPathSelected: { selectedLearningPath in
                           
                            print("Creating Assigned Learning Path based on: \(selectedLearningPath.title)")
                            
                            createAssignedLearningPath(basedOn: selectedLearningPath)
                            
                            assignLearningPathIsPresented = false
                            refreshTrigger.toggle() // Trigger a refresh if needed
                        })
                    }
                }
            }
        }
    }
 
    
    func createAssignedLearningPath(basedOn selectedLearningPath: LearningPath) {
        // create a new assigned learning path
        let newAssignedLearningPath = AssignedLearningPath()
        
        // set up the new learning path title and skills list
        newAssignedLearningPath.setup(basedOn: selectedLearningPath)
        
        
        // create the assigned skills based on the assigned learning path, and add those assigned skill IDs to the learning path's list of assignedSkillIDs
        createAssignedSkills(basedOn: newAssignedLearningPath)
        
        // ##########################
        // THIS IS THE LINE WITH THE ERROR
        // This line is throwing an "object already managed by realm" error

        $student.assignedLearningPaths.append(newAssignedLearningPath)

        // ############################
    }
    
    func createAssignedSkills(basedOn assignedLearningPath: AssignedLearningPath) {
        print("Now in createAssignedSkills(basedOn...)")
        
        print("Iterating over the skills in assignedLearningPath.skills")
        var i = 1
        // for every skill in the skills list, create a new AssignedSkill, and copy the assignedSkill ID to the assignedSkillIDs list
        for skill in assignedLearningPath.skills {
            print("Skill #\(i)")
            print("Creating new AssignedSkill...")
            // create a new assigned skill with default values
            let assignedSkill = AssignedSkill(skillID: skill.id)
            print("Adding to database...")
            // add this new assigned skill to the student in the realm
            $student.assignedSkills.append(assignedSkill)
            print("Adding AssignedSkill.id to assignedLearningPath.assignedSkillIDs...")
            // add the assignedSkill UUID to assignedLearningPath
            assignedLearningPath.assignedSkillIDs.append(assignedSkill.id)
            
            i += 1
        }
    }
}

I don’t understand why

$student.assignedSkills.append(assignedSkill) in the createAssignedSkills() function is NOT throwing an error, but

$student.assignedLearningPaths.append(newAssignedLearningPath) DOES throw an error.

I do have a realm configuration line:

    Realm.Configuration.defaultConfiguration = config

I have run into similar problems before. I’ve been using ChatGPT heavily to help me figure out ways around it, like making sure it’s the managedObject or what have you. But I lack a fundamental understanding of how the realm instances are being used.

I really wish it could just always be the same realm instance unless I specifically ask for an async, so I wouldn’t run into these problems. (Though, that might be a naive desire based on my limited understanding.)

I do have a couple of lines of async code written, but in a different part of the app that is not being used in this code.

I’m not sure what else to include. Thanks for your help!

Potentially, the error could be a result of the other two objects AssignedLearningPath and AssignedSkill.

It may help if we could see those models - and maybe the Student model as well.

Just a guess.

Hi Jay, thanks for the quick reply.

class AssignedLearningPath: EmbeddedObject, Identifiable {
    @Persisted var id: UUID = UUID()
    @Persisted var title: String = ""
    @Persisted var skills: List<Skill>
    // @Persisted var status: Status
    @Persisted var assignedSkillIDs: List<UUID>
    
    func setup(basedOn selectedLearningPath: LearningPath) {
            
            self.title = selectedLearningPath.title
            print("Title set to: \(self.title)")
        
            self.skills.append(objectsIn: selectedLearningPath.skills)
            print("Skills added: \n\(self.skills)")
        
        }
}

//
//  AssignedSkill.swift
//  Grallify
//
//  Created by Andrew Grall on 11/11/23.
//

import Foundation
import RealmSwift

/// An AssignedSkill is a skill that's assigned to a student.
/// Example:
/// Skill: C Major
/// Hands: enum (left / right / separate / together / notSet)
/// Focus: enum (identify / play / sing / listen / read / write / etc.)
///
class AssignedSkill: EmbeddedObject, Identifiable {
    @Persisted var id: UUID = UUID() // Unique identifier. Not primaryKey since it's an embedded object.
    @Persisted var skillID: ObjectId // Reference to the Skill ID
    @Persisted var tasks: List<AssignedSkillTask>
    @Persisted var hands: List<Hands> // left, right, both separately, both together
    @Persisted var focus: List<Focus> // identify, play, sing, listen, read, etc.
    @Persisted var tempo: String = "" // bpm @ quarter notes
    @Persisted var chordPosition: List<ChordPosition> // root, first inversion, etc.
    @Persisted var range: Range = .notSet // how many octaves, one through seven
    // TODO: Notes needs to be an array. It holds current notes to the student about the assigned skill. Notes can be checked off as they're no longer relevant, or completed. See StudentSnapshot for examples in comments. ((Might have changed my mind about this))
    
    @Persisted var notes: String = "" // notes about this particular assigned skill for this student.
    @Persisted var status: Status = .assigned // set to assigned to begin with
    @Persisted var dateAssigned: Date // date when skill was assigned (automatically set to date of AssignedSkill creation
    @Persisted var dateCompleted: Date? // date when skill was completed (by definition will not be set on creation)
    @Persisted var datePaused: Date? // date when skill was paused
    
    var title: String {
        if let skill = RealmManager.fetchSkill(withID: skillID) {
            return skill.title
        }
        // else
        return ""
    }
    
    var shortDescription: String {
            var descriptionParts: [String] = []

            if !hands.isEmpty {
                descriptionParts.append("Hands: \(hands.map { $0.rawValue }.joined(separator: ", "))")
            }
            if !focus.isEmpty {
                descriptionParts.append("Focus: \(focus.map { $0.rawValue }.joined(separator: ", "))")
            }
            if !tempo.isEmpty {
                descriptionParts.append("Tempo: \(tempo)")
            }
            if !chordPosition.isEmpty {
                descriptionParts.append("Position: \(chordPosition.map { $0.rawValue }.joined(separator: ", "))")
            }
            if range != .notSet {
                descriptionParts.append("Range: \(range.rawValue)")
            }

            return descriptionParts.joined(separator: ", ")
        }


    
    convenience init(
        skillID: ObjectId,
        hands: [Hands] = [],
        focus: [Focus] = [],
        tempo: String = "",
        chordPosition: [ChordPosition] = [],
        range: Range = .notSet,
        notes: String = "",
        status: Status = .assigned,
        dateAssigned: Date = Date(),
        dateCompleted: Date? = nil,
        datePaused: Date? = nil
    ) {
        self.init()
        self.skillID = skillID
        
        if hands.isEmpty && focus.isEmpty && tempo.isEmpty && chordPosition.isEmpty && range == .notSet {
                setDefaultValues()
            } else {
                self.hands.append(objectsIn: hands)
                self.focus.append(objectsIn: focus)
                self.tempo = tempo
                self.chordPosition.append(objectsIn: chordPosition)
                self.range = range
            }

            self.notes = notes
            self.status = status
            self.dateAssigned = dateAssigned
            self.dateCompleted = dateCompleted
            self.datePaused = datePaused
        
    }

    enum Status: String, PersistableEnum {
            case assigned = "Assigned" // teacher has assigned but student hasn't begun working on it.
            case inProgress = "In Progress" // student has done something from their side to actively start working on it. Teacher can set this manually or it can be set automatically by student interacting with it from their learning hub.
            case completed = "Completed" // only set by teacher manually
            case paused = "Paused" // Represents skills that are temporarily set aside
        }

    enum Hands: String, PersistableEnum, CaseIterable {
        case left = "Left Hand"
        case right = "Right Hand"
        case together = "Both Hands Together"
        
        var order: Int {
                switch self {
                case .right: return 0
                case .left: return 1
                case .together: return 2
                }
            }

    }
    
    enum Range: String, PersistableEnum, CaseIterable {
        case oneOctave = "One Octave"
        case twoOctaves = "Two Octaves"
        case threeOctaves = "Three Octaves"
        case fourOctaves = "Four Octaves"
        case fiveOctaves = "Five Octaves"
        case sixOctaves = "Six Octaves"
        case sevenOctaves = "Seven Octaves"
        case notSet = ""
    }
    
    enum ChordPosition: String, PersistableEnum, CaseIterable {
        case rootPosition = "Root Position"
        case firstInversion = "First Inversion"
        case secondInversion = "Second Inversion"
        case thirdInversion = "Third Inversion"
        
        // declaring the order so when user sees positions listed on an assigned skill details view, they're in positional order instead of alphabetical or non-ordered.
        var order: Int {
                switch self {
                case .rootPosition: return 0
                case .firstInversion: return 1
                case .secondInversion: return 2
                case .thirdInversion: return 3
                }
            }

    }
    
    enum Focus: String, PersistableEnum, CaseIterable {
        case identify = "Identify"
        case play = "Play"
        case memorize = "Memorize"
        case sing = "Sing"
        case listen = "Listen"
        case read = "Read"
        case write = "Write"
        case improvise = "Improvise"
        case analyze = "Analyze"
    }
}

// MOCK SKILL
extension AssignedSkill {
    static func mock() -> AssignedSkill {
        let assignedSkill = AssignedSkill()
        // Set the properties of assignedSkill as needed for the preview
        assignedSkill.notes = "Sample notes for the assigned skill."
        return assignedSkill
    }
}

// SET DEFAULT VALUES
extension AssignedSkill {
    
    func setDefaultValues() {
        if let skill = RealmManager.fetchSkill(withID: skillID) {
            
            switch skill.type {
            case .chord:
                self.hands.append(objectsIn: [.left, .right])
                self.focus.append(objectsIn: [.play])
                self.chordPosition.append(objectsIn: [.rootPosition])
                self.range = .notSet
            case .scale:
                self.hands.append(objectsIn: [.left, .right])
                self.focus.append(objectsIn: [.play])
                self.range = .oneOctave
                // Add cases for other skill types if needed
            default:
                break
            }
        }
    }
}


//
//  Student.swift
//  Grallify
//
//  Created by Andrew Grall on 11/8/23.
//

import Foundation
import RealmSwift

class Student: Object, Identifiable {
    @Persisted(primaryKey: true) var id: ObjectId
    @Persisted var firstName: String
    @Persisted var lastName: String
    
    @Persisted var isChild: Bool = true // students might be self-managed adults or parent-managed children
    @Persisted var parents = List<Parent>() // if student is a self-managed adult, this list will be empty

    @Persisted var email: String // email address
    @Persisted var phoneNumber: String
    @Persisted var address: String // physical address
    @Persisted var assignedSkills = List<AssignedSkill>() // a list of AssignedSkills, which are embedded objects which reference Skill objects.
    @Persisted var assignedMusicPieces = List<AssignedMusicPiece>() // a list of AssignedMusicPieces, which are embedded objects which reference MusicPiece objects.
    @Persisted var assignedLearningPaths = List<AssignedLearningPath>() // a list of AssignedLearningPaths
    @Persisted var currentNotes: String = "" // current notes about the student
    @Persisted var dateCreated: Date = Date() // keep track of when this student was created
    
    // if applicable, the student group this Student belongs to
    @Persisted(originProperty: "students") var belongsToStudentGroup: LinkingObjects<StudentGroup>
    @Persisted(originProperty: "students") var belongsToFamily: LinkingObjects<Family>

    
    var fullName: String {
            "\(firstName) \(lastName)"
        }
    
    // to reference in code when we need to display whatever property about the student we have available. 
    var shortName: String {
        if firstName.count > 0 {
            return firstName
        }
        else if lastName.count > 0 {
            return lastName
        }
        else if email.count > 0 {
            return email
        }
        else if phoneNumber.count > 0 {
            return phoneNumber
        }
        else {
            return ""
        }
    }
    
    // return an Int of how many skills the student has completed
    var completedSkillsCount: Int {
            return assignedSkills.filter { $0.status == .completed }.count
        }
    
    // return an Int of how many assigned Music Pieces the student has completed
    var completedMusicPiecesCount: Int {
        return assignedMusicPieces.filter { $0.status == .completed }.count
    }


    override class func primaryKey() -> String? {
        "id"
    }
    
}

extension Student {
    // Helper static method to create mock data for previews
    static func mock() -> Student {
        let student = Student()
        student.firstName = "FirstName"
        student.lastName = "LastName"
        student.isChild = true
        student.email = "sample@student.com"
        student.phoneNumber = "123-456-7890"
        student.address = "123 Main St"
        student.currentNotes = "Here are some general notes about the student. He continues to progress. His focus is getting better each time. We are spending less time correcting behavior and more time focusing on the actual musical skills. His extra practice time at home is paying off."

        // Create a mock Skill
        let sampleSkill1 = Skill() // Assuming Skill has a default initializer
        sampleSkill1.title = "Sample Skill 1"
        sampleSkill1.descriptionText = "Sample description of the sample skill."

        // Create a mock AssignedSkill
        let assignedSkill1 = AssignedSkill()
        assignedSkill1.skillID = sampleSkill1.id
        student.assignedSkills.append(assignedSkill1)
        
        // Create a mock Skill
        let sampleSkill2 = Skill() // Assuming Skill has a default initializer
        sampleSkill2.title = "Sample Skill 2"
        sampleSkill2.descriptionText = "Sample description of the sample skill."

        // Create a mock AssignedSkill
        let assignedSkill2 = AssignedSkill()
        assignedSkill2.skillID = sampleSkill2.id
        student.assignedSkills.append(assignedSkill2)

        
        // Create a mock Skill
        let sampleSkill3 = Skill() // Assuming Skill has a default initializer
        sampleSkill3.title = "Sample Skill 3"
        sampleSkill3.descriptionText = "Sample description of the sample skill."

        // Create a mock AssignedSkill
        let assignedSkill3 = AssignedSkill()
        assignedSkill3.skillID = sampleSkill3.id
        student.assignedSkills.append(assignedSkill3)

        return student
    }
}

Right off the bat, here’s one potential issue in the Student model:

class Student: Object, Identifiable {
    @Persisted(primaryKey: true) var id: ObjectId
    .
    .
    .
    override class func primaryKey() -> String? {
        "id"
    }
}

You’re already defined the primary key as an ObjectId, but then the override is a String. I really have not tried that before so it may not be an issue but it smells funny. Remove the override.

as a side note, be careful with this

@Persisted var parents = List<Parent>()

As List is a name collision between Realm and SwiftUI. Always implicitly define it

@Persisted var parents = RealmSwift.List<Parent>()

Thank you. The override string was from a tutorial. I’ll remove.

Is the List conflicted even when importing RealmSwift?

Yep. Replace all of the List with RealmSwift.List to be on the safe side. It may have nothing to do with it but, we have seen numerous instances where things unexpectedly went wonky.

Thanks for the help. I have replaced List<> with RealmSwift.List<> everywhere, and removed the override id in the Student object.

Alas, the problem persists.

Forgive my ignorance, but, how do I tell which object the realm error is referring to?

If this line of code:

        $student.assignedLearningPaths.append(newAssignedLearningPath)

… is the problem (and when I comment it out, there’s no crash, so I think it is)
Is the error referring to $student or newAssignedLearningPath?

2024-02-14 08:51:46.716099-0600 Grallify[11945:8228691] *** Terminating app due to uncaught exception 'RLMException', reason: 'Object is already managed by another Realm. Use create instead to copy it into this Realm.'
*** First throw call stack:
(
	0   CoreFoundation                      0x00007ff8004288ab __exceptionPreprocess + 242
	1   libobjc.A.dylib                     0x00007ff80004dba3 objc_exception_throw + 48
	2   Grallify                            0x0000000106f44405 _ZN18RLMAccessorContext12createObjectEP11objc_objectN5realm12CreatePolicyEbNS2_6ObjKeyE + 1829
	3   Grallify                            0x0000000106f45fa3 _ZN18RLMAccessorContext5unboxIN5realm3ObjEEET_P11objc_objectNS1_12CreatePolicyENS1_6ObjKeyE + 83
	4   Grallify                            0x0000000106f52ebe _ZZN5realm4List3addIRU8__strongP11objc_object18RLMAccessorContextEEvRT0_OT_NS_12CreatePolicyEENKUlS9_E_clIPNS_3ObjEEEDaS9_ + 94
	5   Grallify                            0x0000000106f52791 _ZN5realmL14switch_on_typeINS_3ObjEZNS_4List3addIRU8__strongP11objc_object18RLMAccessorContextEEvRT0_OT_NS_12CreatePolicyEEUlSB_E_EEDaNS_12PropertyTypeEOS9_ + 337
	6   Grallify                            0x0000000106f52322 _ZNK5realm4List8dispatchIZNS0_3addIRU8__strongP11objc_object18RLMAccessorContextEEvRT0_OT_NS_12CreatePolicyEEUlSA_E_EEDaSB_ + 66
	7   Grallify                            0x0000000106f51dbd _ZN5realm4List3addIRU8__strongP11objc_object18RLMAccessorContextEEvRT0_OT_NS_12CreatePolicyE + 253
	8   Grallify                            0x0000000106f61355 _ZZN5realm4List6assignIRU8__strongP11objc_object18RLMAccessorContextEEvRT0_OT_NS_12CreatePolicyEENKUlSA_E_clIS5_EEDaSA_ + 85
	9   Grallify                            0x0000000106f611c3 _ZN27RLMStatelessAccessorContext20enumerate_collectionIZN5realm4List6assignIRU8__strongP11objc_object18RLMAccessorContextEEvRT0_OT_NS1_12CreatePolicyEEUlSC_E_EEvS5_SC_ + 467
	10  Grallify                            0x0000000106f60b4f _ZN5realm4List6assignIRU8__strongP11objc_object18RLMAccessorContextEEvRT0_OT_NS_12CreatePolicyE + 207
	11  Grallify                            0x0000000106f60523 _ZN5realm6Object23set_property_value_implIU8__strongP11objc_object18RLMAccessorContextEEvRT0_RKNS_8PropertyET_NS_12CreatePolicyEb + 867
	12  Grallify                            0x0000000106f45e14 _ZN5realm6Object6createIU8__strongP11objc_object18RLMAccessorContextEES0_RT0_RKNSt3__110shared_ptrINS_5RealmEEERKNS_12ObjectSchemaET_NS_12CreatePolicyENS_6ObjKeyEPNS_3ObjE + 3860
	13  Grallify                            0x0000000106f4484d _ZN18RLMAccessorContext12createObjectEP11objc_objectN5realm12CreatePolicyEbNS2_6ObjKeyE + 2925
	14  Grallify                            0x0000000106f45fa3 _ZN18RLMAccessorContext5unboxIN5realm3ObjEEET_P11objc_objectNS1_12CreatePolicyENS1_6ObjKeyE + 83
	15  Grallify                            0x00000001070129a2 _ZN5realm4List6insertIRU8__strongKP11objc_object18RLMAccessorContextEEvRT0_mOT_NS_12CreatePolicyE + 178
	16  Grallify                            0x0000000107016f6c ___ZL15RLMInsertObjectP15RLMManagedArrayP11objc_objectm_block_invoke + 124
	17  Grallify                            0x00000001070174aa _ZL24translateCollectionErrorIRU8__strongU13block_pointerFvvEEDaOT_P8NSString + 42
	18  Grallify                            0x0000000107017770 _ZL11changeArrayIZL11changeArrayP15RLMManagedArray16NSKeyValueChangemU13block_pointerFvvEE4$_22EvS1_S2_S4_OT_ + 544
	19  Grallify                            0x0000000107012b1d _ZL11changeArrayP15RLMManagedArray16NSKeyValueChangemU13block_pointerFvvE + 77
	20  Grallify                            0x00000001070121cc _ZL15RLMInsertObjectP15RLMManagedArrayP11objc_objectm + 348
	21  Grallify                            0x0000000107012030 -[RLMManagedArray addObject:] + 64
	22  Grallify                            0x000000010730059c $s10RealmSwift4ListC6appendyyxF + 220
	23  Grallify                            0x000000010739f81a $s10RealmSwift15BoundCollectionPAASo13RLMObjectBaseC7ElementRczAA14ThreadConfinedAGRQAA4ListCyAGG5ValueRtzrlE6appendyyAGFyAKXEfU_ + 970
	24  Grallify                            0x0000000107388efd $s10RealmSwift5write33_06F2B43D1E2DA64D3C5AC1DADA9F5BA7LLyyx_yxXEtAA14ThreadConfinedRzlFyyXEfU_ + 61
	25  Grallify                            0x00000001073d0454 $s10RealmSwift5write33_06F2B43D1E2DA64D3C5AC1DADA9F5BA7LLyyx_yxXEtAA14ThreadConfinedRzlFyyXEfU_TA + 36
	26  Grallify                            0x000000010735d335 $s10RealmSwift0A0V5write16withoutNotifying_xSaySo20RLMNotificationTokenCG_xyKXEtKlF + 197
	27  Grallify                            0x0000000107388db2 $s10RealmSwift5write33_06F2B43D1E2DA64D3C5AC1DADA9F5BA7LLyyx_yxXEtAA14ThreadConfinedRzlF + 1042
	28  Grallify                            0x000000010739ef0b $s10RealmSwift15BoundCollectionPAAE5write33_06F2B43D1E2DA64D3C5AC1DADA9F5BA7LLyyy5ValueQzXEAA14ThreadConfinedAGRQrlF + 251
	29  Grallify                            0x000000010739f436 $s10RealmSwift15BoundCollectionPAASo13RLMObjectBaseC7ElementRczAA14ThreadConfinedAGRQAA4ListCyAGG5ValueRtzrlE6appendyyAGF + 150
	30  Grallify                            0x0000000106c4b634 $s8Grallify24AssignedLearningPathViewV06createbcD07basedOnyAA0cD0C_tF + 436
	31  Grallify                            0x0000000106c4b40f $s8Grallify24AssignedLearningPathViewV4bodyQrvg7SwiftUI19_ConditionalContentVyAE7ForEachVy05RealmG04ListCyAA0bcD0CGAnE4TextVGAE0E0PAEE5sheet11isPresented9onDismiss7contentQrAE7BindingVySbG_yycSgqd__yctAeSRd__lFQOyAE6ButtonVyAQG_AE15NavigationStackVyAE0xD0VAA06AssigncD6ScreenVGQo_GyXEfU_A10_ycfU1_A9_yXEfU_yAA0cD0CcfU_ + 671
	32  Grallify                            0x0000000106da7061 $s8Grallify24AssignLearningPathScreenV4bodyQrvg7SwiftUI6ButtonVyAE4TextVGAA0cD0CcfU_yycfU_ + 177
	33  SwiftUI                             0x00000001112be8d5 block_destroy_helper.53 + 3190
	34  SwiftUI                             0x0000000111268a1c objectdestroy.142Tm + 41107
	35  SwiftUI                             0x00000001111d8280 __swift_memcpy81_8 + 10488
	36  SwiftUI                             0x0000000111268a1c objectdestroy.142Tm + 41107
	37  SwiftUI                             0x0000000111268a30 objectdestroy.142Tm + 41127
	38  SwiftUI                             0x0000000111268a1c objectdestroy.142Tm + 41107
	39  SwiftUI                             0x0000000110f7ec59 block_destroy_helper + 36990
	40  SwiftUI                             0x0000000110f7e5ba block_destroy_helper + 35295
	41  SwiftUI                             0x0000000111371827 __swift_memcpy64_4 + 139048
	42  SwiftUI                             0x000000011137373e __swift_memcpy64_4 + 147007
	43  UIKitCore                           0x000000010cbccccc -[UICollectionView _selectItemAtIndexPath:animated:scrollPosition:notifyDelegate:deselectPrevious:performCustomSelectionAction:] + 1515
	44  UIKitCore                           0x000000010cc091fa -[UICollectionView _userSelectItemAtIndexPath:] + 219
	45  UIKitCore                           0x000000010cc094a9 -[UICollectionView touchesEnded:withEvent:] + 672
	46  UIKitCore                           0x000000010d714906 forwardTouchMethod + 312
	47  UIKitCore                           0x000000010d714906 forwardTouchMethod + 312
	48  UIKitCore                           0x000000010d714906 forwardTouchMethod + 312
	49  UIKitCore                           0x000000010d714906 forwardTouchMethod + 312
	50  UIKitCore                           0x000000010d0d523f _UIGestureEnvironmentUpdate + 9811
	51  UIKitCore                           0x000000010d0d2792 -[UIGestureEnvironment _updateForEvent:window:] + 844
	52  UIKitCore                           0x000000010d72943b -[UIWindow sendEvent:] + 5282
	53  UIKitCore                           0x000000010d6fccae -[UIApplication sendEvent:] + 898
	54  UIKit                               0x0000000117051608 -[UIApplicationAccessibility sendEvent:] + 85
	55  UIKitCore                           0x000000010d7a5861 __dispatchPreprocessedEventFromEventQueue + 9381
	56  UIKitCore                           0x000000010d7a7f69 __processEventQueue + 8334
	57  UIKitCore                           0x000000010d79e2a1 __eventFetcherSourceCallback + 272
	58  CoreFoundation                      0x00007ff800387fe5 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
	59  CoreFoundation                      0x00007ff800387f24 __CFRunLoopDoSource0 + 157
	60  CoreFoundation                      0x00007ff800387721 __CFRunLoopDoSources0 + 212
	61  CoreFoundation                      0x00007ff800381e23 __CFRunLoopRun + 927
	62  CoreFoundation                      0x00007ff8003816a7 CFRunLoopRunSpecific + 560
	63  GraphicsServices                    0x00007ff809cb128a GSEventRunModal + 139
	64  UIKitCore                           0x000000010d6dbad3 -[UIApplication _run] + 994
	65  UIKitCore                           0x000000010d6e09ef UIApplicationMain + 123
	66  SwiftUI                             0x00000001118c9667 __swift_memcpy93_8 + 11936
	67  SwiftUI                             0x00000001118c9514 __swift_memcpy93_8 + 11597
	68  SwiftUI                             0x0000000110f2d7e9 __swift_memcpy195_8 + 12255
	69  Grallify                            0x0000000106eaaa2e $s8Grallify0A3AppV5$mainyyFZ + 30
	70  Grallify                            0x0000000106eaab39 main + 9
	71  dyld                                0x000000010bd8f2bf start_sim + 10
	72  ???                                 0x00000001194e752e 0x0 + 4719539502
)
libc++abi: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'RLMException', reason: 'Object is already managed by another Realm. Use create instead to copy it into this Realm.'
terminating with uncaught exception of type NSException
CoreSimulator 857.14 - Device: iPhone 11 Pro Max (B66870F7-14D4-4D04-8EDB-6D3B7C35C0D9) - Runtime: iOS 16.2 (20C52) - DeviceType: iPhone 11 Pro Max

Kind of a crazy issue but here’s my first guess. This code modifies an object that’s passed in, and I believe that object is already tied to (created on) ‘another Realm’.

func createAssignedSkills(basedOn assignedLearningPath: AssignedLearningPath) { 
   assignedLearningPath.assignedSkillIDs.append(assignedSkill.id)

At long last, figured out the object managed by another realm issue for assigned learning paths.

AssignedLearningPath model had a setup function which appended skills from a LearningPath model.

Those skills were the managed objects the realm was referring to.

I changed it so we don’t append those skill objects but just hold the IDs of them in an array.

Everything works now.

Thanks so much for your time @Jay
You pointed me in the right direction.

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