0

I'm trying to write an array of objects using NSKeyedArchiver.

Here some parts from my code:

EventStore.swift - holding the event array:

class EventStore{

    private var events: [EventItem] = [EventItem]()
    static let sharedStore = EventStore()

    private init() {
    }


    static func getEventFile() -> URL{
        let directory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        let file = directory.appendingPathComponent("events.bin")
        return file
    }

    func addEvent(withEvent event:EventItem){
        events.append(event)
    }

    func getEvents()->[EventItem]{
        return events
    }

}

No the eventItem where I implemented NSCoding:

class EventItem: NSObject, NSCoding {

    private var id:Int
    private var timestamp:Int64

    //Object initialization
    init(withId id:Int,withTimestamp timestamp:Int64) {
        self.id = id
        self.timestamp = timestamp
    }

    required convenience init?(coder: NSCoder) {
        //get value from stored key if exists
        guard let id = coder.decodeObject(forKey: "id") as? Int,
            let timestamp = coder.decodeObject(forKey: "timestamp") as? Int64

        //exit init after decoding if a value is missing
        else {
            NSLog("Unable to decode event")
            return nil
        }

        self.init(withId:id,withTimestamp:timestamp)
    }

    func getId()->Int{
        return id
    }

    func getTimestamp()->Int64{
        return timestamp
    }

    //encode values to keys
    func encode(with aCoder: NSCoder) {
        NSLog("Encoding event")
        aCoder.encode(id, forKey: "id")
        aCoder.encode(timestamp, forKey: "timestamp")
    }

}

Finally when the user tape on a button I'm adding an event into the array and saving it:

var eventStore = EventStore.sharedStore

    @IBAction func TakeAction() {

        //generate new event
        let timestamp = Int64(NSDate().timeIntervalSince1970 * 1000)
        let newEvent = EventItem(withId: eventStore.eventCount(), withTimestamp: timestamp)
        eventStore.addEvent(withEvent: newEvent)
        saveEvents()

        //refresh ui
        updateTakeText()

    }

    func saveEvents(){
           do{
               let data = try NSKeyedArchiver.archivedData(withRootObject: eventStore.getEvents(), requiringSecureCoding: false)
               NSLog("Data being written : \(data)")
               try data.write(to: EventStore.getEventFile())
               NSLog("Write events to file :\(EventStore.getEventFile())")
           }catch{
               NSLog(error.localizedDescription)
           }
       }

       func loadEvents() {
           do{
               let data = try Data(contentsOf: EventStore.getEventFile())
               NSLog("Data loaded from file path: \(data)")

               //try get data else return empty array
               let events = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? [EventItem] ?? [EventItem]()
               NSLog("Events retrived from file: \(events.count)")
               eventStore.setEvents(withEvents:events)
           }catch{
               NSLog(error.localizedDescription)
           }
       }

I added a lot of debug and it seems that the encoding and file write are working fine but the decoding fail. It always get nil values.

Any clue?

Thanks in advance

Pierre Anken
  • 308
  • 2
  • 16

1 Answers1

0

When encoding Int values you have to decode them with coder.decodeInteger(forKey: "xxx")

Pierre Anken
  • 308
  • 2
  • 16