Ch. 16, NSKeyedArchiver.archiveRootObject deprecated

Hi there,

the documentation is not helpful here :frowning:
what can I use to archive data instead of archiveRootObject?

Any help appreciated.
Zoltán

Edit: Okay, I could solve it myself:
I used the new ‘Codable’-Protocol instead of NSCoding. With Codable the initialization is automagic, you only have to declare the class or struct to conform to Codable:

class Item: NSObject, Codable {…

No need to implement encode and required init!

In itemStore.swift:

    func saveChanges() -> Bool {
        print("Saving items to \(itemArchiveURL.path)")
        do {
            let data = try PropertyListEncoder().encode(allItems)
            try data.write(to: itemArchiveURL)
            return true
        } catch {
            print("Error saving items: \(error) ")
        }
        return false
    }

EDIT 2:
The data is now written to the filesystem, but I do not manage to read it again. Any help appreciated.

EDIT 3:
I helped myself :slight_smile:

init() {
    typealias allItemsType = [Item]?
    do {
        let data = try Data(contentsOf: itemArchiveURL)
        let decoder = PropertyListDecoder()
        if let allItems = try decoder.decode(allItemsType.self, from: data){
            self.allItems = allItems
        }
        
    } catch {
        print("itemStore init error: \(error)")
    }
}

archiveRootObject is clearly deprecated, however, the error message suggest using archivedDataWithRootObject:requiringSecureCoding .

Unfortunately, Zoltan’s solution is not working in Xcode 10.2.1 for me. I’m getting the error "Generic parameter ‘Value’ could not be inferred for the .encode line .

Has anyone found the appropriate method to use with Xcode 10.2.1?

I think that this works:
func saveChanges() -> Bool {
print(“Saving items to: (itemsArchiveURL.path)”)

    do {
        let data = try NSKeyedArchiver.archivedData(withRootObject: allItems, requiringSecureCoding: false)
        try data.write(to: itemsArchiveURL)
        return true
    } catch {
        return false
    }
}
2 Likes

Reloading the data was confusing, but I think that this works as well:

init() {
    
    if let data = try? Data(contentsOf: itemsArchiveURL) {
        let archivedItems = try! NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? [Item]
        allItems = archivedItems!
        print("Loaded Archive file")
    } else {
        print("Loading Archive file failed or there's no file to load")
    }
  
}
2 Likes