1

I'm new in Swift and iOS and I came across this issue while making an app. I want to basically store user data using NSCoding onto local storage. However, my code below doesn't do it. Anyone can tell me what's wrong with it? Much appreciated!

Also, both saveChecklist and LoadChecklist are called in appDelegate, under applicationDidEnterBackground and applicationWillTerminate.

I have a feeling my issue lies in encodeWithCoder and init(aDecoder), as I used GET to append my Checklist item into lists.

My code in DataModel.class:

import Foundation

class DataModel: NSObject, NSCoding {
var checklist = Checklist()
var lists: [Checklist] {
    get {
        return [checklist]
    }
    set {
    }
}

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

// MARK: - All the saving stuff

func encodeWithCoder(aCoder: NSCoder) {
    aCoder.encodeObject(checklist, forKey: "Checklist")
}

required init?(coder aDecoder: NSCoder) {
    checklist = aDecoder.decodeObjectForKey("Checklist") as! Checklist
}

func documentsDirectory() -> String {
    let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,    .UserDomainMask, true)

    return paths[0]
}

func dataFilePath() -> String {
    return (documentsDirectory() as NSString).stringByAppendingPathComponent("Checklist.plist") // create file if no checklist.plist is present
}

func saveChecklist() {
    let data = NSMutableData()
    let archiver = NSKeyedArchiver(forWritingWithMutableData: data)
    archiver.encodeObject(lists, forKey: "Checklists")
    archiver.finishEncoding()

    data.writeToFile(dataFilePath(), atomically: true)
}

func loadChecklist() {
    let path = dataFilePath()
    if NSFileManager.defaultManager().fileExistsAtPath(path) {
        if let data = NSData(contentsOfFile: path) {
            let unarchiver = NSKeyedUnarchiver(forReadingWithData: data)
            lists = unarchiver.decodeObjectForKey("Checklists") as! [Checklist]

            unarchiver.finishDecoding()
        }
    }
}

My code in Checklist.class:

import Foundation

class Checklist: NSObject, NSCoding {
var item = [items]()
var rituals = [items]()
var doneButtonVisible: Bool
var streak: Int
var itemDoneCount: Int
var startDate: NSDate
var dayHasStarted: Bool

override init() {
    doneButtonVisible = false
    itemDoneCount = 0
    streak = 0
    startDate = NSDate()
    dayHasStarted = false
    super.init()
}

// saves
func encodeWithCoder(aCoder: NSCoder) {
    aCoder.encodeObject(item, forKey: "Items")
    aCoder.encodeObject(rituals, forKey: "Rituals")
    aCoder.encodeObject(itemDoneCount, forKey: "ItemDoneCount")
    aCoder.encodeObject(doneButtonVisible, forKey: "DoneButtonVisible")
    aCoder.encodeObject(streak, forKey: "Streak")
    aCoder.encodeObject(startDate, forKey: "StartDate")
    aCoder.encodeObject(dayHasStarted, forKey: "DayHasStarted")
}

// loads
required init?(coder aDecoder: NSCoder) {
    item = aDecoder.decodeObjectForKey("Items") as! [items]
    rituals = aDecoder.decodeObjectForKey("Rituals") as! [items]
    itemDoneCount = aDecoder.decodeObjectForKey("ItemDoneCount") as! Int
    doneButtonVisible = aDecoder.decodeObjectForKey("DoneButtonVisible") as! Bool
    streak = aDecoder.decodeObjectForKey("Streak") as! Int
    startDate = aDecoder.decodeObjectForKey("StartDate") as! NSDate
    dayHasStarted = aDecoder.decodeObjectForKey("DayHasStarted") as! Bool
    super.init()
}

}

UPDATE

Solved the saving and loading issue by revamping my data model. Using Core Data instead to save and load data.

However, I still have no idea as to why the above code does not load. Apparently, it does not save the contents of checklist to begin with.

1 Answer 1

1

Your Checklist class needs to inherit from NSCoding too, and implement the encodeWithCoder(coder: NSCoder) method. This is a good tutorial on NSCoding.

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

3 Comments

Hi, thanks for your answer! However my Checklist does inherit from NSCoding and it still does not work. I'll update the post to include it just so you can check it.
Ok, in what way doesn't your code work? Do you get an error thrown when you try to load or save? Or is the data just recreated incorrectly/missing some stuff?
There was no error thrown, just that the data either did not load when the app was restarted or the data did not save to begin with. If I did not use the GET method, and just append a checklist item into dataModel in a viewController, it works. I believe it has got to do with the GET method. Anyway, I've decided to use Core Data to store it, and revamped my whole data model and now it works. I still have no idea why the code above does not work though.

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.