Saving Array with NSCoding

Amit picture Amit · Aug 16, 2015 · Viewed 10k times · Source

I have a small app that has a few saving functionalities. I have a data model class called: Closet:

class Department: NSObject, NSCoding {
   var deptName = ""
   var managerName = ""

   var Task: [Assignment]?   // <----- assignment class is in example 2

   func encodeWithCoder(aCoder: NSCoder) {

    aCoder.encodeObject(deptName, forKey: "deptName")
    aCoder.encodeObject(managerName, forKey: "mngName")
   // aCoder.encodeObject(Task, forKey: "taskArray")

}

  required init(coder aDecoder: NSCoder) {

     super.init()

    course = aDecoder.decodeObjectForKey("deptName") as! String
    instructor = aDecoder.decodeObjectForKey("mngName") as! String
   // Task = aDecoder.decodeObjectForKey("tasKArray") as? [Assignment]

}

override init() {
    super.init()
}

}

So this is the main controller data model which in the first View Controller, a user is able to tap the "+" button to add a department name and manager name. The problem is not with saving this as i save it successfully using NSKeyedArchive and loads it back when the app starts.

The Problem:

I want to add an array of assignments on this data model Department called Assignment which would have a title and a notes variable. This is the Data model for Assignment:

Assignment.swift

class Assignment: NSObject, NSCoding {
     var title = ""
     var notes = ""

      func encodeWithCoder(aCoder: NSCoder) {

    // Methods
    aCoder.encodeObject(title, forKey: "Title")
    aCoder.encodeObject(notes, forKey: "notepad")

}

required init(coder aDecoder: NSCoder) {


// Methods
    title = aDecoder.decodeObjectForKey("Title") as! String
    notes = aDecoder.decodeObjectForKey("notepad") as! String

    super.init()
}

override init() {
    super.init()
}


 }

So what i am essentially trying to achieve is an app where a user enters different departments with different manager names which work now in my app, but within a department, the user can click the "+" button to add an assignment title and notes section that can be editable when clicked which i can handle afterwards. These assignments are different from department to department.

My big problem is achieving this functionality. I can't seem to get this working.

I want this array assigment property to be part of the Department Class so each cell can have their own sort of To-Do list. any help would definitely help me out a lot. Thanks :)

Answer

Tone416 picture Tone416 · Aug 29, 2015

You are using NSCoder correctly, but there are two errors in capitalization. The first error affects the functionality of the application, and the second error is a stylistic mistake. You encoded Task with the key "taskArray", but you tried to decode it with the key "tasKArray". If you fix the capital K in the latter, then your code will work.

The second capitalization error is a stylistic mistake: Task, like all properties in Swift, should be written in lowerCamelCase (llamaCase).

Be sure to pay close attention to indentation. In programming, there are special indentation rules we follow that help make code clear. Here is the corrected code with proper capitalization and indentation:

class Department: NSObject, NSCoding {
    var deptName = ""
    var managerName = ""

    var task: [Assignment]?

    func encodeWithCoder(aCoder: NSCoder) {
        aCoder.encodeObject(deptName, forKey: "deptName")
        aCoder.encodeObject(managerName, forKey: "mngName")
        aCoder.encodeObject(task, forKey: "taskArray")
    }

    required init(coder aDecoder: NSCoder) {
        super.init()

        course = aDecoder.decodeObjectForKey("deptName") as! String
        instructor = aDecoder.decodeObjectForKey("mngName") as! String
        task = aDecoder.decodeObjectForKey("taskArray") as? [Assignment]
    }

    override init() {
        super.init()
    }
}

class Assignment: NSObject, NSCoding {
    var title = ""
    var notes = ""

    func encodeWithCoder(aCoder: NSCoder) {
        // Methods
        aCoder.encodeObject(title, forKey: "Title")
        aCoder.encodeObject(notes, forKey: "notepad")
    }

    required init(coder aDecoder: NSCoder) {
        // Methods
        title = aDecoder.decodeObjectForKey("Title") as! String
        notes = aDecoder.decodeObjectForKey("notepad") as! String

        super.init()
    }

    override init() {
        super.init()
    }
}