Search code examples
iosswiftarchivenscoding

NSCoding in Swift not archiving data properly?


I'm relatively new to iOS development in general, but I'm coding this app.

I have custom objects "Semester", "Course", and "Assignments". Semesters contain arrays of courses and courses contain arrays of assignments. I'm able to properly archive the semester and course information, but for some reason the assignment information can't be read.

Semester:

required init?(coder aDecoder: NSCoder) {
    self.name = ""

    super.init()

    if let archivedName = aDecoder.decodeObject(forKey: "name") as? String {
        name = archivedName
    }
    if let archivedCourses = aDecoder.decodeObject(forKey: "courses") as? [Course] {
        courses = archivedCourses
    }
}

func encode(with aCoder: NSCoder) {
    aCoder.encode(name, forKey: "name")
    aCoder.encode(courses, forKey: "courses")
}

Course:

required init?(coder aDecoder: NSCoder) {
    self.name = ""
    super.init()

    if let archivedName = aDecoder.decodeObject(forKey: "courseName") as? String {
        name = archivedName
    }
    if let archivedAssignments = aDecoder.decodeObject(forKey: "assignments") as? [Assignment] {
        assignments = archivedAssignments
    }
}

func encode(with aCoder: NSCoder) {
    aCoder.encode(name, forKey: "courseName")
    aCoder.encode(assignments, forKey: "assignments")

Assignment:

required init?(coder aDecoder: NSCoder) {
    self.name = ""
    self.grade = 0
    self.weight = 0
    super.init()

    if let archivedName = aDecoder.decodeObject(forKey: "assignmentName") as? String, let archivedGrade = aDecoder.decodeObject(forKey: "assignmentGrade") as? Int, let archivedWeight = aDecoder.decodeObject(forKey: "assignmentWeight") as? Int {
        name = archivedName
        grade = archivedGrade
        weight = archivedWeight
    }
}

func encode(with aCoder: NSCoder) {
    aCoder.encode(name, forKey: "assignmentName")
    aCoder.encode(grade, forKey: "assignmentGrade")
    aCoder.encode(weight, forKey: "assignmentWeight")
}

I'm not sure why but the assignment details can't be read when I try to decode the object.


Solution

  • I Usually decode Int like this

    if decoder.containsValue(forKey: "teamNumber"){
        self.teamNumber = decoder.decodeInteger(forKey: "teamNumber")
    }
    

    translated to your issue will be like this, change the init?(coder aDecoder: NSCoder)method of your Assignment class

    required init?(coder aDecoder: NSCoder) {
    
        self.name = ""
        self.grade = 0
        self.weight = 0
        super.init()
    
        if let archivedName = aDecoder.decodeObject(forKey: "assignmentName") as? String{
          self.name = archivedName
        } 
    
        if decoder.containsValue(forKey: "assignmentGrade"){
            self.grade = decoder.decodeInteger(forKey: "assignmentGrade")
        }
    
        if decoder.containsValue(forKey: "assignmentWeight"){
            self.weight = decoder.decodeInteger(forKey: "assignmentWeight")
        }
    
    }
    

    Hope this helps