Search code examples
swiftnsuserdefaults

How to save array of objects (with image variables) in Swift and Xcode?


I am wondering how to save an array of objects from the following class:

class CustomDocument: NSObject, NSCoding {
    let name : String
    let image : UIImage

    init(n: String, i: UIImage){
        name = n
        image = i
    }

    //other code excluded
}

Originally, I saved this array to User Defaults. Because the objects took up a lot of space, it caused a lot of lag in the app.

What is the best way to save an array of data that takes up a lot of space?

Thank you so much for the help and all responses are appreciated.


Solution

  • Try this code, Hope it helps:

    class CustomDocument: NSObject, NSCoding  {
    
        var name : String?
        var image : UIImage?
    
        func encode(with aCoder: NSCoder) {
            aCoder.encode(name, forKey: "namekey")
            if let imageData = image!.jpegData(compressionQuality: 1.0){
                aCoder.encode(imageData, forKey: "imagekey")
            }
            UserDefaults.standard.synchronize()
        }
    
        required convenience init?(coder aDecoder: NSCoder) {
            self.init()
            if let name =  (aDecoder.decodeObject(forKey: "namekey") as? String){
                self.name = name
            }
            if let imageData = (aDecoder.decodeObject(forKey: "imagekey")  as? Data){
                if let image = UIImage(data: imageData){
                    self.image = image
                }
            }
        }
    }
    
    
    func archiveDocument(document:CustomDocument) -> Data? {
        do {
            let archivedObject = try NSKeyedArchiver.archivedData(withRootObject: document, requiringSecureCoding: false)
            return archivedObject
    
        } catch {
            // do something with the error
        }
        return nil
    }
    
    
    func unarchiveDocument(unarchivedObject:Data) -> CustomDocument? {
        do {
            if let document = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(unarchivedObject) as? CustomDocument {
                return document
            }
        } catch {
            // do something with the error
        }
        return nil
    }
    

    Example:

    //Set the object, also you can use an array instead of an object
    let obj = CustomDocument()
    obj.name = "doc1"
    obj.image = UIImage(named: "my_image")
    if let archivedObject = archiveDocument(document: obj){
        UserDefaults.standard.set(archivedObject, forKey: "obj")
    }
    
    //Get the object
    if let  archivedObject = UserDefaults.standard.data(forKey: "obj"){           
        obj = unarchiveDocument(unarchivedObject: archivedObject)
        let myImage = obj?.image
    }