以 swift 元组作为值的 NSCoding swift 字典

NSCoding swift dictionary with swift tuple as values

我有一个 Swift 字典,其中键作为字符串,值作为 Swift 元组。我想将这本字典发送到其他设备,所以我需要在这本字典上实现 NSCoding。任何人都可以帮助我如何实现这一目标。以下是我的字典代码。

class STCTruthDict: NSObject, NSCoding, SequenceType {

   typealias IpRelationshipTuple = (String, String?)

   private var truthDict: [String : IpRelationshipTuple] = [ : ]

   subscript(key: String) -> IpRelationshipTuple? {
     get {
       return self.truthDict[key]
     }
     set {
       truthDict[key] = newValue
     }
   }

   // MARK: - Initializers

   override init() {
     super.init()
   }

   required init(coder aDecoder: NSCoder) {
     self.truthDict = aDecoder.decodeObjectForKey("truthDict") as! [String : IpRelationshipTuple]
     let key = aDecoder.decodeObjectForKey("user_id") as? String
     let ip = aDecoder.decodeObjectForKey("tupleIp") as? String
     let groupId = aDecoder.decodeObjectForKey("tupleGroupId") as? String
   }

   func encodeWithCoder(aCoder: NSCoder) {
      for (key, tuple) in self.truthDict {
            aCoder.encodeObject(key, forKey: "user_id")
            aCoder.encodeObject(tuple.Ip, forKey: "tupleIp")
            aCoder.encodeObject(tuple.groupId, forKey: "tupleGroupId")
        }       
   }

   func generate() -> DictionaryGenerator <String, IpRelationshipTuple> {
    return self.truthDict.generate()
   }

}

您 运行 遇到的问题是元组是 structs 而不是 class (对象)类型。当您尝试执行以下操作时,您会注意到此问题:

if let dictionary = aDecoder.decodeObjectForKey("truthDict") as? [String : RelationshipType] { ... }

不幸的是,在尝试处理 Swift 中的值类型时会出现这个问题。要绕过此限制,您可以使用通用 Box class 将值类型框起来,如下所示:

class Box<T>
{
    var value : T?

    init(_ value: T?)
    {
        self.value = value
    }
}

使用 Box class,您可以使用它来编码和解码您的字典元组:

class TruthDictionary : NSObject, NSCoding, SequenceType
{
    typealias RelationshipType = (ip: String, groupId: String?)

    private var dictionary = [String : RelationshipType]()

    subscript(key: String) -> RelationshipType?
    {
        get { return self.dictionary[key] }
        set { self.dictionary[key] = newValue }
    }

    // MARK: - Initializers

    override init()
    {
        super.init()
    }

    // MARK: - NSCoding

    required init(coder aDecoder: NSCoder)
    {
        // Unbox each tuple from the decoded dictionary
        if let boxedDictionary = aDecoder.decodeObjectForKey("truthDict") as? [String : Box<RelationshipType>]
        {
            for (key, boxedTuple) in boxedDictionary
            {
                self.dictionary[key] = boxedTuple.value
            }
        }
    }

    func encodeWithCoder(aCoder: NSCoder)
    {
        var boxedDictionary = [String: Box<RelationshipType>]()

        // Box each tuple to the dictionary to be encoded
        for (key, tuple) in self.dictionary
        {
            boxedDictionary[key] = Box(tuple)
        }

        aCoder.encodeObject(boxedDictionary, forKey: "truthDict")
    }

    // MARK: - SequenceType

    func generate() -> DictionaryGenerator<String, RelationshipType>
    {
        return dictionary.generate()
    }
}