Как кодировать initwithcoder в Swift?

Я новичок в Swift, и у меня проблема с initwithcoder в Swift.

У меня есть класс UserItem, мне нужно сохранить логин пользователя.

в цели c это так

 - (id)initWithCoder:(NSCoder *)decoder{
    if (self = [super init]){
        self.username = [decoder decodeObjectForKey:@"username"];
    }
    return self;
}

и быстро я пытаюсь так

override init() {
   super.init()
}    

required init(coder decoder: NSCoder!) {

   self.username = (decoder.decodeObjectForKey("username")?.stringValue)!

   super.init(coder: decoder)
}

но если как указано выше, я получаю ошибку в коде

super.init(coder: decoder)

сообщение об ошибке: «дополнительный аргумент« кодер »в вызове

я больше не могу понять, поэтому я пробую этот код,

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

   self.username = (decoder.decodeObjectForKey("username")?.stringValue)!
}

но получить ошибку

.UserItem initWithCoder:]: unrecognized selector sent to instance 0x7fd4714ce010

что я должен делать? Спасибо за вашу помощь.


person Dian Sigit    schedule 30.11.2015    source источник
comment
есть класс UserItem Покажите его объявление, пожалуйста.   -  person matt    schedule 30.11.2015


Ответы (1)


Я боролся с NSCoding (протокол, который вы используете для архивирования и разархивирования объектов) в прошлом, и я вижу, что вы проходите через те же боли. Надеюсь, это немного уменьшит это:

class UserItem: NSObject, NSCoding {
    var username: String
    var anInt: Int

    init(username: String, anInt: Int) {
        self.username = username
        self.anInt = anInt
    }

    required init?(coder aDecoder: NSCoder) {
        // super.init(coder:) is optional, see notes below
        self.username = aDecoder.decodeObjectForKey("username") as! String
        self.anInt = aDecoder.decodeIntegerForKey("anInt")
    }

    func encodeWithCoder(aCoder: NSCoder) {
        // super.encodeWithCoder(aCoder) is optional, see notes below
        aCoder.encodeObject(self.username, forKey: "username")
        aCoder.encodeInteger(self.anInt, forKey: "anInt")
    }

    // Provide some debug info
    override var description: String {
        get {
            return ("\(self.username), \(self.anInt)")
        }
    }
}

// Original object
let a = UserItem(username: "michael", anInt: 42)

// Serialized data
let data = NSKeyedArchiver.archivedDataWithRootObject(a)

// Unarchived from data
let b = NSKeyedUnarchiver.unarchiveObjectWithData(data)!

print(a)
print(b)

Важно сопоставить ключи и типы данных в encodeWithCoder(aCoder:) (функция архивирования) и init(coder:) (функция разархивирования).

Что сбивает с толку новичков, так это то, что делать с суперклассом. Вы должны включать суперкласс в две приведенные выше функции только в том случае, если сам суперкласс соответствует NSCoding. NSObject сам по себе этого не обеспечивает. Идея в том, что каждый класс знает о своих свойствах, некоторые из которых являются закрытыми. Если суперкласс не может архивировать/разархивировать, их не нужно вызывать.

person Code Different    schedule 30.11.2015
comment
Как вызвать базовый/абстрактный UIViewController из файла Nib? - person DShah; 10.02.2016
comment
У меня есть похожий код, но в моем случае компилятор просит добавить удобства в required init?(coder aDecoder: NSCoder). Что мешает мне вызвать super.(init: coder). Я что-то пропустил? - person Frédéric Adda; 11.05.2016
comment
разве вы не должны вызывать super.init()? - person Olivier de Jonge; 12.12.2016