Search This Blog

Friday, September 22, 2017

NSCoding Protocol and how to use it

Implementing NSCoding Protocol


NSCoding is simple protocol with two methods. If we want to save our custom class with all its fields we need to implement this protocol. Class that conform to NSCoding protocol can be serialized and deserialized into data.

public func encode(with aCoder: NSCoder)

public init?(coder aDecoder: NSCoder)

Implementation of our custom class that confirm NSCoding protocol
import Foundation
import UIKit

class AppSettings: NSObject, NSCoding {
    
    var themeColor: UIColor
    var userName: String
    var isActivated: Bool
    var lastActivityDate: Date
    var count: Int
    
    func encode(with aCoder: NSCoder) {
        aCoder.encode(self.themeColor, forKey: "themeColor")
        aCoder.encode(self.userName, forKey: "userName")
        aCoder.encode(self.isActivated, forKey: "isActivated")
        aCoder.encode(self.lastActivityDate, forKey: "lastActivityDate")
        aCoder.encode(self.count, forKey: "count")
    }
    
    required convenience init?(coder aDecoder: NSCoder) {
        
        guard let themeColor = aDecoder.decodeObject(forKey: "themeColor") as? UIColor,
            let userName = aDecoder.decodeObject(forKey: "userName") as? String,
            let lastActivityDate = aDecoder.decodeObject(forKey: "lastActivityDate") as? Date else {
                return nil
        }
        
        self.init(themeColor: themeColor,
                  userName: userName,
                  isActivated: aDecoder.decodeBool(forKey: "isActivated"),
                  lastActivityDate: lastActivityDate,
                  count: aDecoder.decodeInteger(forKey: "count"))
    }
    
    init(themeColor: UIColor, userName: String, isActivated: Bool, lastActivityDate: Date, count: Int) {
        self.themeColor = themeColor
        self.userName = userName
        self.lastActivityDate = lastActivityDate
        self.isActivated = isActivated
        self.count = count
    }
    
}


Using NSKeyedArchiver and NSKeyedUnrachiver we can implement saving and loading of data that we get from serizlization/deserizlization of our object (that is instance of custom class that confirm NSCoding protocol)

Save object with NSKeyedArchiver

let data = NSKeyedArchiver.archivedData(withRootObject: self.appSettings)
let userDefaults = UserDefaults.standard
userDefaults.set(data, forKey: "appSettings")

Load object with NSKeyedUnrachiver

let userDafaults = UserDefaults.standard
if let data = userDafaults.object(forKey: "appSettings") as? Data {
    self.appSettings = NSKeyedUnarchiver.unarchiveObject(with: data) as! AppSettings
} else {
    self.appSettings = AppSettings(themeColor: UIColor.red,
                                           userName: "John",
                                           isActivated: true,
                                           lastActivityDate: Date(),
                                           count: 22)
}

Sources

http://nshipster.com/nscoding/
https://habrahabr.ru/company/inetra/blog/185918/
https://itvdn.com/ru/blog/article/it-intriduction-ios-dev-part7

Problems and errors

In order to make NSCoding work you need to declare the super class NSObject.
class AppSettings: NSObject, NSCoding {
    ...
}
Crash when implementing NSCoding in Swift

GitHub

Source code on github




No comments:

Post a Comment