1

So I'm having a problem. I'm making this app that currently stores information for "Courses". However, I've been changing the app a lot, and now I want a dictionary of courses. I need to be able to save this dictionary of courses and load it from any class.

Currently in Course.swift I have the NSCoding setup. My program writes and reads all course information. But now I want to change it so that it writes this dictionary instead of all the courses. I don't have another data class that holds this dictionary, it's just being held in my "StartUpViewController.swift".

class Course: NSObject, NSCoding {

// MARK: Properties
var courseName : String
var projects : [String]
var projectMarks : [Double]
var projectOutOf : [Double]
var projectWeights : [Double]

// MARK: Archiving Paths

static let DocumentsDirectory = FileManager().urls(for: .documentDirectory, in: .userDomainMask).first!
static let ArchiveURL = DocumentsDirectory.appendingPathComponent("courses")
// MARK: Types

struct PropertyKey {
    static let courseNameKey = "courseName"
    static let projectsKey = "projects"
    static let projectMarksKey = "projectMarks"
    static let projectOutOfKey = "projectOutOf"
    static let projectWeightsKey = "projectWeights"
}

// MARK: NSCoding

func encode(with aCoder: NSCoder) {
    aCoder.encode(courseName, forKey: PropertyKey.courseNameKey)
    aCoder.encode(projects, forKey: PropertyKey.projectsKey)
    aCoder.encode(projectMarks, forKey: PropertyKey.projectMarksKey)
    aCoder.encode(projectOutOf, forKey: PropertyKey.projectOutOfKey)
    aCoder.encode(projectWeights, forKey: PropertyKey.projectWeightsKey)
}

required convenience init?(coder aDecoder: NSCoder) {
    let courseName = aDecoder.decodeObject(forKey: PropertyKey.courseNameKey) as! String
    let projects = aDecoder.decodeObject(forKey: PropertyKey.projectsKey) as! [String]
    let projectMarks = aDecoder.decodeObject(forKey: PropertyKey.projectMarksKey) as! [Double]
    let projectOutOf = aDecoder.decodeObject(forKey: PropertyKey.projectOutOfKey) as! [Double]
    let projectWeights = aDecoder.decodeObject(forKey: PropertyKey.projectWeightsKey) as! [Double]

    self.init(courseName: courseName, projects: projects, projectMarks: projectMarks, projectOutOf: projectOutOf, projectWeights: projectWeights)
}

How do I go about doing this? Do I keep the Course.swift using NSCoding, or do I have to only put NSCoding in my View Controller?

class StartUpViewController: UIViewController {

var groups: [String: [Course]?] = [:]

...
}

1 Answer 1

2

Create a new class conforming to NSCoding.

This new class has a property :

var courses: [String : Course]?

And the methods :

func encode(with aCoder: NSCoder) {
    if let courses = courses {
        aCoder.encode(courses, forKey: "courses")
    }
}

required convenience init?(coder aDecoder: NSCoder) { 
    courses = aDecoder.decodeObject(forKey: "courses") as? [String : Course]
    }

And leave your NSCoding protocol implementation in Course class because it will be used when encoding the dictionary.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your reply, I just have one more question. Now when I go to save everything, do I only have to save the "groups" or do I have to make a call to save all the courses as well?
You just have to save the group, which will save the courses recursively automatically.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.