create a class using NSCoding

2019-09-19 14:21发布

问题:

in my first project I was creating a class using the following code:

import Foundation

class Rate { 
    var currency: String!
    var sellRate: String!
    var buyRate: String!

    init (data: NSDictionary) {
        self.currency = getStringFromJSON(data, key:"CurrencyName")
        self.sellRate = getStringFromJSON(data, key:"SellRate")
        self.buyRate = getStringFromJSON(data, key:"BuyRate")
    }

    func getStringFromJSON(data: NSDictionary, key: String) -> String {
        if let info = data[key] as? String {
            return info
        }
        return ""
    }
}

I am scratching my head of how to update code to use NSCoding. I need to use NSKeyedArchiver that is why objects should conform to the NSCoding protocol.

I have working example which I found in GitHub, but still I fail to write working code. Example:

class Book: NSObject, NSCoding {
    var title: String!
    var author: String!

    required convenience init(coder decoder: NSCoder) {
        self.init()

        self.title = decoder.decodeObjectForKey("title") as! String?
        self.author = decoder.decodeObjectForKey("author")as! String?
    }

    func encodeWithCoder(coder: NSCoder) {
        coder.encodeObject(self.title, forKey: "title")
        coder.encodeObject(self.author, forKey: "author")
    }   
}

回答1:

Try this:

class Rate : NSObject, NSCoding {
    var currency: String!
    var sellRate: String!
    var buyRate: String!

    init (_ data: NSDictionary) {
        super.init()
        self.currency = getStringFromJSON(data, key:"CurrencyName")
        self.sellRate = getStringFromJSON(data, key:"SellRate")
        self.buyRate = getStringFromJSON(data, key:"BuyRate")
    }

    func getStringFromJSON(data: NSDictionary, key: String) -> String {
        if let info = data[key] as? String {
            return info
        }
        return ""
    }

    // NSCoding protocol implementation
    @objc func encodeWithCoder(coder : NSCoder) {
        coder.encodeObject(self.currency, forKey:"currency")
        coder.encodeObject(self.sellRate, forKey:"sellRate")
        coder.encodeObject(self.buyRate, forKey:"buyRate")
    }

    @objc required init(coder aDecoder: NSCoder) {
        self.currency = aDecoder.decodeObjectForKey("currency") as! String
        self.sellRate = aDecoder.decodeObjectForKey("sellRate") as! String
        self.buyRate = aDecoder.decodeObjectForKey("buyRate") as! String
    }
}

// Usage
let dict = [
    "CurrencyName": "USD",
    "SellRate": "1.12",
    "BuyRate": "1.1"
] 

let r1 = Rate(dict)

// Archive it
let data = NSKeyedArchiver.archivedDataWithRootObject(r1)

// Get it back
let r2 = NSKeyedUnarchiver.unarchiveObjectWithData(data) as! Rate
print(r2.currency)
print(r2.sellRate)
print(r2.buyRate)

Changes to your original code:

  1. The data label in your init was made optional with a _.
  2. Because your Rate class inherits from NSObject now, it must call super.init()
  3. Added implementation for NSCoding protocol

SwiftStub



回答2:

You already have code for the answer. Your Rate class has three data instances: currency, sellrate, and buyrate. Your sample code used title and author. Add the : NSObject, NSCoding after Rate. Copy your sample code into your class. Change all occurrences of title to currency, then duplicate all of these lines but then changing currency to sellrate on these duplicate lines, and change author to buyrate.