Save and get objects using NSKeyedArchiver and NSKeyedUnarchiver Swift 5

If you want to save your objects in the directory then, you are in the right article.
Here we are going to save objects in the document directory which supports NSCoding protocol. We are going to achieve this using NSKeyedArchiver and NSKeyedUnarchiver class which are defines under the Foundation framework.
We can save Array, String, Dictionary, Set, UIView, UIColor, etc.
we can even save Int, Double, Float, etc.
Add below UIViewController extension in your project.
extension UIViewController {
    
    // Save object in document directory
    func saveObject(fileName: String, object: Any) -> Bool {
        
        let filePath = self.getDirectoryPath().appendingPathComponent(fileName)//1
        do {
            let data = try NSKeyedArchiver.archivedData(withRootObject: object, requiringSecureCoding: false)//2
            try data.write(to: filePath)//3
            return true
        } catch {
            print("error is: \(error.localizedDescription)")//4
        }        
        return false
    }
    
    // Get object from document directory
    func getObject(fileName: String) -> Any? {
        
        let filePath = self.getDirectoryPath().appendingPathComponent(fileName)//5
        do {
            let data = try Data(contentsOf: filePath)//6
            let object = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data)//7
            return object//8
        } catch {
            print("error is: \(error.localizedDescription)")//9
        }
        return nil
    }
    
    //Get the document directory path
    //10
    func getDirectoryPath() -> URL {
        let arrayPaths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        return arrayPaths[0]
    }
}

1: File name must be unique for your object otherwise, it will overwrite the older object if saved with same name. Using fileName we are creating a directory file path URL
2: Create a Data using an object with NSKeyedArchiver class function archivedData.
3: Save this data at the above URL path.
4: Check if there is an error while saving the Data.
5: When you are fetching the object from directory, provide the same file name using which you have saved it. Using the file name create file path URL.
6: Get the Data from file path URL.
7: Convert Data into object using NSKeyedUnarchiver class function unarchiveTopLevelObjectWithData.
8: Return the object.
9: Catch the error while retrieving our object.
10: This function returns the document directory path URL.

Move to your UIViewController Class

Open your ViewViewController class and inside your viewDidLoad function add below code.
override func viewDidLoad() {
    super.viewDidLoad()
    
    // Your object that needs to be save
    let array = ["iPhone", "Macbook Pro", "iPad", "Watch"]
    // Save your objet
    if self.saveObject(fileName: "myArray", object: array) {
        print("saved")
    } else {
        print("not saved")
    }
    
    // Get your object
    if let value = self.getObject(fileName: "myArray") as? [String] {
        print("value is: \(value)")
    }
}

Saving the custom class object

As discussed earlier we can save the custom class object which confirms NSCoding protocol. Suppose we have a custom Car as below.
class Car: NSObject, NSCoding {
    
    var brand: String?
    var madel: String?
    
    func encode(with aCoder: NSCoder) {
        aCoder.encode(self.madel, forKey:"madel")
        aCoder.encode(self.brand, forKey:"brand")
    }
    
    required init?(coder aDecoder: NSCoder) {
        self.madel = aDecoder.decodeObject(forKey:"madel") as? String
        self.brand = aDecoder.decodeObject(forKey:"brand") as? String
    }
    
    init(barand: String, model: String) {
        self.brand = barand
        self.madel = model
    }
}

As we can see this class is confirms the NSCoding protocol so we can save it using below the code.
let car = Car(barand: "Audi", model: "A4")
if self.saveObject(fileName: "myCar", object: car) {
    print("saved")
} else {
    print("not saved")
}

// Get the saved Car object
if let car = self.getObject(fileName: "myCar") as? Car {
    print("my car is: \(car)")
}
We can even save the Array of Car.

Read our next Article: Sending data from iPhone to Apple Watch

Leave a Reply

Your email address will not be published. Required fields are marked *