0

Here I want to archive and unarchive my custom class,here is the code snippet.

enum Type: Int {
case Fruit
case Meat
case Drink
}

class ShoppingList {

    var typeOne: [Type]!

    var typeTwo: [Type]!

    var typeThree: [Type]!

    init(coder aDecoder: NSCoder) {

        // how to decode enum-based array
    }

    func encodeWithCoder(aCoder: NSCoder) {

        // how to encode enum-based array
    }
}

I am wondering how to implement these two methods.

tounaobun
  • 14,570
  • 9
  • 53
  • 75
  • You can convert that to an `NSDictionary`, and store that within a json / plist file. Or use `NSArchiver` if you look for something more compact (ie bytes instead of xml/json). – Khanh Nguyen Dec 03 '14 at 02:49
  • 1
    The idea is to encode / decode your instance variables so that you can reconstruct them from the coder. Do that however you like. Thinking up a way to represent an array of Types (terrible choice of name, by the way) as an archivable object is completely up to you. Just remember that what goes in must come out; you need a representation that is exactly reversible. – matt Dec 03 '14 at 03:07
  • Thanks,matt.I have figured out a solution based on your suggestion. – tounaobun Dec 03 '14 at 03:18

1 Answers1

1

How about something like this?:

class ShoppingList: NSObject, NSCoding {

    var typeOne: [Type]!

    var typeTwo: [Type]!

    var typeThree: [Type]!

    override init() {
        super.init()
    }

    required init(coder aDecoder: NSCoder) {
        let nils = aDecoder.decodeObjectForKey("nils") as [Bool]
        if nils[0] {
            typeOne = nil
        } else {
            let typeOneInt = aDecoder.decodeObjectForKey("typeOneInt") as [Int]
            self.typeOne = typeOneInt.map{Type(rawValue: $0) ?? .Fruit}
        }
        if nils[1] {
            typeTwo = nil
        } else {
            let typeTwoInt = aDecoder.decodeObjectForKey("typeTwoInt") as [Int]
            self.typeTwo = typeTwoInt.map{Type(rawValue: $0) ?? .Fruit}
        }
        if nils[2] {
            typeThree = nil
        } else {
            let typeThreeInt = aDecoder.decodeObjectForKey("typeThreeInt") as [Int]
            self.typeThree = typeThreeInt.map{Type(rawValue: $0) ?? .Fruit}
        }
    }

    func encodeWithCoder(aCoder: NSCoder) {
        let nils:[Bool] = [typeOne == nil, typeTwo == nil, typeThree == nil]
        aCoder.encodeObject(nils, forKey:"nils")

        if typeOne != nil {
            let typeOneInt:[Int] = typeOne.map{$0.rawValue}
            aCoder.encodeObject(typeOneInt, forKey:"typeOneInt")
        }
        if typeTwo != nil {
            let typeTwoInt:[Int] = typeTwo.map{$0.rawValue}
            aCoder.encodeObject(typeTwoInt, forKey:"typeTwoInt")
        }
        if typeThree != nil {
            let typeThreeInt:[Int] = typeThree.map{$0.rawValue}
            aCoder.encodeObject(typeThreeInt, forKey:"typeThreeInt")
        }
    }
}

Comments:

  1. I wanted to capture the fact the lists could be nil. This is stored in a boolean array called "nils".
  2. The map function is used to convert the arrays of enums to [Int] which hold raw values.
vacawama
  • 150,663
  • 30
  • 266
  • 294