CoreData: error: Row (pk = 1) for entity 'ResidentInfo' is missing mandatory text data for property 'name'

I know that this has been posted many times, but I am facing an issue where I can't save a model instance. I know that this is due to enums from others trying to find solutions.

The error that shows: CoreData: error: Row (pk = 2) for entity 'ResidentInfo' is missing mandatory text data for property 'name'

Solutions that I've tried:

  • removed all enums from their respective structs to being standalone.
  • making sure all enum calls use the full keyPath
  • removing CustomStringConvertible from all enums and moving them to rawValue strings
  • updating Xcode to 15.4b
  • probably other things I've forgotten at this point

File is too long to fit in post or comments (I'm sorry it's insanely long, it's a complex model), so I'll try to fit what I can where, are there anythings that stand out that may be an issue?

Enums:

enum Gender: String, CaseIterable, Codable {
    case male = "Male"
    case female = "Female"
    case transmale = "Trans Male"
    case transfemale = "Trans Female"
    case nonbinary = "Nonbinary"
    case other = "Other"
}

enum BodyBuild: String, CaseIterable, Codable {
    case small = "Small"
    case medium = "Medium"
    case large = "Large"
}

enum Status: String, Codable {
    case incomplete, complete
}

enum HairColor: String, CaseIterable, Codable {
    case black = "Black"
    case blonde = "Blonde"
    case dirtyBlonde = "Dirty Blonde"
    case brown = "Brown"
    case lightBrown = "Light Brown"
    case darkBrown = "Dark Brown"
    case red = "Red"
}

enum EyeColor: String, CaseIterable, Codable {
    case blue = "Blue"
    case brown = "Brown"
    case black = "Black"
    case green = "Green"
    case hazel = "Hazel"
    case gray = "Gray"
    case heterochromatic = "Heterochromatic"
}

enum RaceEthnicity: String, CaseIterable, Codable {
    case native = "American Indian or Alaska Native"
    case asian = "Asian"
    case black = "Black or African American"
    case pi = "Native Hawaiian or Other Pacific Islander"
    case white = "White"
    case mixed = "2 or More Races/Mixed"
}

enum MarkType: String, CaseIterable, Codable {
    case birthMark = "Birth Mark"
    case scar = "Scar"
    case tattoo = "Tattoo"
    case piercing = "Piercing"
    case other = "Other"
}

enum heightFormatStyle: String {
    case short, long, hash
}

enum suicideRiskLevel: String, Codable {
    case low = "Low"
    case medium = "Medium"
    case high = "High"
}

enum MedicationFrequency: String, CaseIterable, Codable {
    case daily = "Daily"
    case weekly = "Weekly"
    case biweekly = "Bi-Weekly"
    case monthly = "Monthly"
    case asNeeded = "As Needed"
    case temporary = "Temporary Use"
    case other = "Other"
}

enum SchoolOption: String, CaseIterable, Codable {
    case ged = "GED"
    case communityCollege = "Community College"
    case university = "4-Year College"
}

enum FamilyDiseaseTypes: String, CaseIterable, Codable {
    case alcoholism = "Alcoholism"
    case asthma = "Asthma"
    case cancer = "Cancer"
    case drugAbuse = "Drug Abuse"
    case hypertension = "High Blood Pressure"
    case nervousBreakdown = "Nervous Breakdown"
    case sca = "Sickle Cell Anemia"
    case seizures = "Convulsions, Seizures Epilepsy"
    case allergies = "Allergies"
    case birthDefect = "Birth Defect"
    case diabetes = "Diabetes"
    case heartDisease = "Heart Disease"
    case migraines = "Migraine Headaches"
    case obesity = "Obesity"
    case tuberculosis = "Tuberculosis"
    case thyroid = "Glandular/Thyroid Issues"
}

Structs:

struct IdentifyingInformation: Codable {
    var hairColor: HairColor = HairColor.black
    var height: Height = Height(feet: 5, inches: 8)
    var race: RaceEthnicity = RaceEthnicity.native
    var build: BodyBuild = BodyBuild.small
    var eyeColor: EyeColor = EyeColor.blue
    var hispanic: Bool = false
    var distinguishingMarks: [DistinguishingMark] = []

    var currentLivingSitutation: String = ""
    var currentSupportServices: String = ""

    struct DistinguishingMark: Codable, Identifiable {
        var id: UUID = UUID()
        var type: MarkType = MarkType.tattoo
        var location: String = ""
        var description: String = ""
        var photos: [Data] = []
    }

    struct Height: Codable {
        var feet: Int
        var inches: Int

        func formatted(formatStyle: HeightFormatStyle = .short) -> String {
            switch formatStyle {
            case HeightFormatStyle.hash:
                return "\(feet)'\(inches)\""
            case HeightFormatStyle.long:
                return "\(feet) feet \(inches) inches"
            case HeightFormatStyle.short:
                return "\(feet)ft \(inches)in"
            }
        }
    }
}

struct EmergencyNeeds: Codable {
    var food: Bool = false
    var shelter: Bool = false
    var clothing: Bool = false
    var hygeine: Bool = false
    var medical: Bool = false
    var mentalHealth: Bool = false
    var otherNeeds: String = ""
    var abuseNeglectAllegations: Bool = false
    var abuseReport: AbuseReport? = nil

    struct AbuseReport: Codable {
        var reportAccepted: Bool = false
        var whoAccepted: String = ""
        var reportNumber: String = ""
    }
}

struct RiskAssessment: Codable {
    var selfHarm: Bool = false
    var selfHarmAttempt: Bool = false
    var selfHarmExplanation: String? = nil
    var currentFeelings: String? = nil
    var dangerToOthers: Bool = false
    var dangerToOthersExplanation: String? = nil
    var suicideAssessmentRequired: Bool {
        return selfHarm || dangerToOthers
    }
}

struct SuicideAssessment: Loopable, Codable {
    var dateCompleted: Date = Date()
    var familyMember: Bool = false
    var treatedMentalIllness: Bool = false
    var chronicIllness: Bool = false
    var historyOfSelfDestructiveBehavior: Bool = false
    var recentLoss: Bool = false
    var isolatedAloneHopeless: Bool = false
    var goodbyeNoteOrPosessionDelegation: Bool = false
    var plan: Bool = false
    var betterOff: Bool = false
    var wishToDie: Bool = false
    var manualReview: Bool = false
    var comments: String = ""
    var helpCallMade: Bool = false
    var riskLevel: suicideRiskLevel {
        let riskScore = try? allProperties().reduce(0) { result, property in
            if let isTrue = property.value as? Bool, isTrue {
                return result + 1
            } else {
                return result
            }
        }
        switch riskScore! {
        case 0 ... 3:
            return .low
        case 4 ... 7:
            return .medium
        default:
            return .high
        }
    }
}

[Continued in comments]

  • There are a ton more structs, but I don't want to inundate this thread before necessary

Add a Comment

Replies

Main model:

@Model
class ResidentInfo: Codable {
    @Attribute(.unique)
    var id: UUID
    var status: Status = Status.incomplete
    var date: Date = Date()
    var completingStaffMember: StaffMember? = nil
    @Attribute(.unique)
    var residentNumber: Int? = nil
    var personalInfo: PersonalInfo
    var identifyingInformation: IdentifyingInformation
    var presentingProblems: String
    var emergencyNeeds: EmergencyNeeds
    var medicalInfo: MedicalInfo
    var riskAssessment: RiskAssessment
    var psychAssessment: PsychAssessment
    var legal: Legal
    var homelessHistory: HomelessHistory
    var employment: EmploymentDetails
    var education: EducationDetails
    var substanceUse: SubstanceUse
    var sexualBehavior: SexualBehavior
    var independenceAssessment: IndependentLivingAssessment
    var consentForServices: ConsentForServices
    var photoVideoRelease: PhotoVideoRelease
    var suicideAssessment: SuicideAssessment
    var healthAssessment: HealthAssessment
    @Attribute(.externalStorage)
    var profilePhoto: Data? = nil
    var _updatedDate: Date

    init() {
        id = UUID()
        personalInfo = PersonalInfo()
        identifyingInformation = IdentifyingInformation()
        presentingProblems = ""
        emergencyNeeds = EmergencyNeeds()
        medicalInfo = MedicalInfo()
        riskAssessment = RiskAssessment()
        psychAssessment = PsychAssessment()
        legal = Legal()
        homelessHistory = HomelessHistory()
        employment = EmploymentDetails()
        education = EducationDetails()
        substanceUse = SubstanceUse()
        sexualBehavior = SexualBehavior()
        independenceAssessment = IndependentLivingAssessment()
        consentForServices = ConsentForServices()
        photoVideoRelease = PhotoVideoRelease()
        suicideAssessment = SuicideAssessment()
        healthAssessment = HealthAssessment()
        _updatedDate = Date()
    }

    private enum CodingKeys: String, CodingKey {
        case id = "_id"
        case status, date, completingStaffMember, residentNumber, personalInfo, identifyingInformation, presentingProblems, emergencyNeeds, medicalInfo, riskAssessment, psychAssessment, legal, homelessHistory, employment, education, substanceUse, sexualBehavior, independenceAssessment, consentForServices, photoVideoRelease, suicideAssessment, healthAssessment, profilePhoto, _updatedDate
    }

    public required init(from decoder: Decoder) throws {
        do {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            id = try container.decode(UUID.self, forKey: .id)
            status = try container.decode(Status.self, forKey: .status)
            date = try container.decode(Date.self, forKey: .date)
            completingStaffMember = try container.decodeIfPresent(StaffMember.self, forKey: .completingStaffMember)!
            residentNumber = try container.decodeIfPresent(Int.self, forKey: .residentNumber)
            personalInfo = try container.decode(PersonalInfo.self, forKey: .personalInfo)
            identifyingInformation = try container.decode(IdentifyingInformation.self, forKey: .identifyingInformation)
            presentingProblems = try container.decode(String.self, forKey: .presentingProblems)
            emergencyNeeds = try container.decode(EmergencyNeeds.self, forKey: .emergencyNeeds)
            medicalInfo = try container.decode(MedicalInfo.self, forKey: .medicalInfo)
            riskAssessment = try container.decode(RiskAssessment.self, forKey: .riskAssessment)
            psychAssessment = try container.decode(PsychAssessment.self, forKey: .psychAssessment)
            legal = try container.decode(Legal.self, forKey: .legal)
            homelessHistory = try container.decode(HomelessHistory.self, forKey: .homelessHistory)
            employment = try container.decode(EmploymentDetails.self, forKey: .employment)
            education = try container.decode(EducationDetails.self, forKey: .education)
            substanceUse = try container.decode(SubstanceUse.self, forKey: .substanceUse)
            sexualBehavior = try container.decode(SexualBehavior.self, forKey: .sexualBehavior)
            independenceAssessment = try container.decode(IndependentLivingAssessment.self, forKey: .independenceAssessment)
            consentForServices = try container.decode(ConsentForServices.self, forKey: .consentForServices)
            photoVideoRelease = try container.decode(PhotoVideoRelease.self, forKey: .photoVideoRelease)
            suicideAssessment = try container.decode(SuicideAssessment.self, forKey: .suicideAssessment)
            healthAssessment = try container.decode(HealthAssessment.self, forKey: .healthAssessment)
            profilePhoto = try container.decodeIfPresent(Data.self, forKey: .profilePhoto)
            _updatedDate = try container.decode(Date.self, forKey: ._updatedDate)
        } catch {
            throw error
        }
    }

    func encode(to encoder: Encoder) {
        do {
            var container = encoder.container(keyedBy: CodingKeys.self)
            try container.encode(id, forKey: .id)
            try container.encode(status, forKey: .status)
            try container.encode(date, forKey: .date)
            try container.encodeIfPresent(completingStaffMember, forKey: .completingStaffMember)
            try container.encodeIfPresent(residentNumber, forKey: .residentNumber)
            try container.encode(personalInfo, forKey: .personalInfo)
            try container.encode(identifyingInformation, forKey: .identifyingInformation)
            try container.encode(presentingProblems, forKey: .presentingProblems)
            try container.encode(emergencyNeeds, forKey: .emergencyNeeds)
            try container.encode(medicalInfo, forKey: .medicalInfo)
            try container.encode(riskAssessment, forKey: .riskAssessment)
            try container.encode(psychAssessment, forKey: .psychAssessment)
            try container.encode(legal, forKey: .legal)
            try container.encode(homelessHistory, forKey: .homelessHistory)
            try container.encode(employment, forKey: .employment)
            try container.encode(education, forKey: .education)
            try container.encode(substanceUse, forKey: .substanceUse)
            try container.encode(sexualBehavior, forKey: .sexualBehavior)
            try container.encode(independenceAssessment, forKey: .independenceAssessment)
            try container.encode(consentForServices, forKey: .consentForServices)
            try container.encode(photoVideoRelease, forKey: .photoVideoRelease)
            try container.encode(suicideAssessment, forKey: .suicideAssessment)
            try container.encode(healthAssessment, forKey: .healthAssessment)
            try container.encodeIfPresent(profilePhoto, forKey: .profilePhoto)
            try container.encode(_updatedDate, forKey: ._updatedDate)
        } catch {
            fatalError()
        }
    }