2015-03-17 1 views
2

У меня есть словарь Swift с ключами как строки и значения как строчные кортежи. Я хотел бы отправить этот словарь на другое устройство, поэтому мне нужно реализовать NSCoding в этом словаре. Может ли кто-нибудь помочь мне в том, как я могу это достичь. Ниже приведен мой словарь.Словарь быстрого доступа 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() 
    } 

} 
+0

Почему бы вам не изменить стратегию и преобразовать словарь в JSON? –

ответ

4

Проблема вы работаете, состоит в том, что кортежи structs и не class (объект) типа. Вы заметите этот вопрос, когда вы пытаетесь сделать следующее:

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

Данные вопросы, к сожалению, приходит немного, пытаясь справиться с типами значений в Swift. Чтобы обойти это ограничение, вы можете боксировать ваши типы значений, используя общий Box класс следующим образом:

class Box<T> 
{ 
    var value : T? 

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

С Box класса, вы можете использовать это, чтобы кодировать и декодировать словарь кортежей:

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() 
    } 
} 
+0

Довольно крутой подход. Однако при использовании этого кода я получаю сообщение об ошибке. Похоже, мне нужно добавить класс NSCoding on Box, и таким образом он будет правильно закодирован. Но это может быть сделано только для подклассов NSObject, я думаю, что я не могу использовать Generics здесь generics, так как не работает с ObjC. Я могу просто использовать RelationType для значения вместо . Пожалуйста, дайте мне знать, если вы считаете, что Im здесь что-то отсутствует. –

Смежные вопросы