2016-01-29 2 views
0

У меня есть класс, который наследуется от NSObject, и я хочу, чтобы он был NSCoding совместимым. Но я столкнулся с проблемой при кодировании массива объектов, которые должны реализовывать протокол.Кодирование/декодирование массива объектов, который реализует протокол в Swift 2

protocol MyProtocol { 
    var myDescription: String { get } 
} 

class DummyClass: NSObject, NSCopying, MyProtocol { 
    var myDescription: String { 
     return "Some description" 
    } 

    func encodeWithCoder(aCoder: NSCoder) { 
     // does not need to do anything since myDescription is a computed property 
    } 

    override init() { super.init() } 
    required init?(coder aDecoder: NSCoder) { super.init() } 
} 

class MyClass: NSObject, NSCoding { 
    let myCollection: [MyProtocol] 

    init(myCollection: [MyProtocol]) { 
     self.myCollection = myCollection 

     super.init() 
    } 

    required convenience init?(coder aDecoder: NSCoder) { 
     let collection = aDecoder.decodeObjectForKey("collection") as! [MyProtocol] 

     self.init(myCollection: collection) 
    } 

    func encodeWithCoder(aCoder: NSCoder) { 
     aCoder.encodeObject(myCollection, forKey: "collection") 
    } 
} 

Для aCoder.encodeObject(myCollection, forKey: "collection") я получаю ошибку:

Cannot convert value of type '[MyProtocol]' to expected argument type 'AnyObject?' 

OK, протокол, очевидно, не является экземпляром класса и поэтому не AnyObject?, но я понятия не имею, как исправить это , Наверное, есть трюк, о котором я не знаю? Или вы выполняете архивацию/сериализацию по-разному в Swift, как в Objective-C?

Там, наверное, проблема с let collection = aDecoder.decodeObjectForKey("collection") as! [MyProtocol] тоже, но компилятор пока не жалуются ...

ответ

1

Я только что нашел решение сам: Ключ к карте myCollection в [AnyObject] и наоборот, например, так:

class MyClass: NSObject, NSCoding { 
    let myCollection: [MyProtocol] 

    init(myCollection: [MyProtocol]) { 
     self.myCollection = myCollection 

     super.init() 
    } 

    required convenience init?(coder aDecoder: NSCoder) { 
     let collection1 = aDecoder.decodeObjectForKey("collection") as! [AnyObject] 

     let collection2: [MyProtocol] = collection1.map { $0 as! MyProtocol } 


     self.init(myCollection: collection2) 
    } 

    func encodeWithCoder(aCoder: NSCoder) { 
     let aCollection: [AnyObject] = myCollection.map { $0 as! AnyObject } 

     aCoder.encodeObject(aCollection, forKey: "collection") 
    }  
} 
0

Я знаю ваше название указывает Swift 2, но только для справки, для подобной проблемы я работал, я обнаружил, что в Swift 3, вам не нужно конвертировать больше AnyObject.

Следующие работы для меня в Swift 3 (используя ваш пример):

class MyClass: NSObject, NSCoding { 
    let myCollection: [MyProtocol] 

    init(myCollection: [MyProtocol]) { 
     self.myCollection = myCollection 
     super.init() 
    } 

    required convenience init?(coder aDecoder: NSCoder) { 
     let collection = aDecoder.decodeObject(forKey: "collection") as! [MyProtocol]  
     self.init(myCollection: collection) 
    } 

    func encodeWithCoder(aCoder: NSCoder) {  
     aCoder.encode(aCollection, forKey: "collection") 
    }  
} 
Смежные вопросы