NSCoding требует инициализатора в унаследованных классах в Swift
У меня есть класс Foo, который соответствует NSCoding
и NSCoding
которые я хочу сохранить в NSKeyedArchiver
Я хочу создать класс Bar, подкласс Foo, который также будет соответствовать NSCoding
и NSCoding
. У меня возникла проблема с пониманием того, как создать required convenience init?(coder aDecoder: NSCoder)
в подклассе.
поэтому класс Foo …
class Foo: NSObject, NSCoding { let identifier:String init(identifier:String) { self.identifier = identifier } override var description:String { return "Foo: \(identifier)" } func encodeWithCoder(aCoder: NSCoder) { aCoder.encodeObject(identifier, forKey: "identifier") } required convenience init?(coder aDecoder: NSCoder) { guard let identifier = aDecoder.decodeObjectForKey("identifier") as? String else { return nil } self.init(identifier:identifier) } }
Затем класс Bar …
- iOS YouTube и похожий на сафари кинопроигрыватель
- iOS - Изменение ширины компонента UIPickerView
- Передача данных для отправки адресата без iVar
- как печатать запрос ответа в хорошем состоянии из raw в ios
- EXEC_BAD_ACCESS на applicationWillEnterForeground в iOS3, но не iOS4
class Bar:Foo { let tag:String init(identifier:String, tag:String) { self.tag = tag super.init(identifier: identifier) } override var description:String { return "Bar: \(identifier) is \(tag)" } }
Я могу получить это, чтобы скомпилировать, добавив следующие методы, чтобы сделать этот NSCoding
совместимый
override func encodeWithCoder(aCoder: NSCoder) { aCoder.encodeObject(tag, forKey: "tag") super.encodeWithCoder(aCoder) }
это имеет смысл, потому что я называю super.encodeWithCoder(...)
повторное использование супер делает это СУХОЙ. Проблема, с которой я сталкиваюсь, заключается в создании required convenience init?(...)
единственный способ, с помощью которого я могу его компилировать, – это сделать это …
required convenience init?(coder aDecoder:NSCoder) { guard let identifier = aDecoder.decodeObjectForKey("identifier") as? String, let tag = aDecoder.decodeObjectForKey("tag") as? String else { return nil } self.init(identifier:identifier, tag:tag) }
Я в основном скопировал требуемый инициализатор суперкласса, а затем добавил дополнительный метод декодирования для свойства подкласса. Этот подход не кажется правильным …
Есть ли лучший способ реализовать это?
- Являются ли идентификаторы селектора чувствительными к типам аргументов?
- Создание ячеек UITableCell в порядке от NSMutableDictionary
- Невозможно добавить NSDictionary в NSArray
- Просмотр папок приложений внутри устройства iPhone
- iOS x координата пальца при нажатии на UIButton
- Правильно ли это запустить общий метод?
- Пользовательский вид, добавленный в навигационную панель
- iPhone: события нажатия кнопок - освободить не стрелять?
Сразу после декодирования и назначения всех свойств подкласса в требуемом методе init вызовите:
super.init(coder: aDecoder)
Я попробовал свой код на детской площадке, он просто автоматически добавляет код, когда я отмечаю красный круг ошибки.
Кодирование походит на вашу функцию, необходимую для удобства init.
образец кода:
required convenience init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }
Подумайте об этом некоторое время и верьте, что это правильный способ реализовать это.
Причина в том, что Swift обеспечивает инициализацию объекта. Инициализаторы удобства могут вызывать только требуемые инициализаторы. Только требуемый инициализатор может вызвать init
на super
.
Поэтому единственный способ инициализировать объект подкласса – это декодировать все требуемые параметры инициализации, прежде чем вы вызовете требуемый инициализатор подкласса … который затем вызывает инициализатор суперкласса
Вот код, который вы можете скопировать на площадку https://gist.github.com/vorlando/dc29ba98c93eaadbc7b1