Я изучаю разработку iOS из онлайн-курса, и каждый раз, когда я создаю настраиваемое представление (настраиваемая ячейка представления таблицы, ячейка представления коллекции и т. Д.), Инструктор всегда реализует этот инициализатор:
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
Почему я всегда должен это звонить? Что оно делает? Могу ли я поместить свойства в init?
NSCoding
вам необходимо реализовать этот инициализатор, поскольку он требуется от классов, реализующихNSCoding
. Вы должны хотя бы вызвать метод инициализации суперкласса. Если онNSCoder
содержит закодированные свойства для вашего класса, вы можете использовать этот метод для их восстановленияОтветы:
Я начну этот ответ с противоположной стороны: что, если вы хотите сохранить состояние вашего представления на диск? Это известно как сериализация . Обратное - десериализация - восстановление состояния объекта с диска.
NSCoding
Протокол определяет два метода для сериализации и десериализации объектов:Так зачем это нужно в вашем пользовательском классе? Ответ - Интерфейсный Разработчик. Когда вы перетаскиваете объект на раскадровку и настраиваете ее, Interface Builder сериализует состояние этого объекта на диск, а затем десериализует его, когда раскадровка появляется на экране. Вам нужно указать Interface Builder, как это сделать. По крайней мере, если вы не добавляете никаких новых свойств в свой подкласс, вы можете просто попросить суперкласс выполнить упаковку и распаковку за вас, отсюда и
super.init(coder: aDecoder)
вызов. Если ваш подкласс более сложный, вам необходимо добавить свой собственный код сериализации и десериализации для подкласса.Это контрастирует с подходом Visual Studio, который заключается в записи кода в скрытый файл для создания объекта во время выполнения.
источник
init(coder aCoder : NSCoder)
?awakeFromNib
это не сработает.awakeFromNib
вызывается во время выполнения . Все, что вы делаете в Интерфейсном Разработчике, происходит во время разработки . Для того, чтобы нести то , что вы сделали в режиме разработки на время выполнения являетсяencodeWithCoder
(экономия) иinit(coder:)
(погрузка)awakeFromNib
илиinitWIthFrame
Требование реализовать этот инициализатор является следствием двух вещей:
Принцип подстановки Лискова . Если S является подклассом T (например,
MyViewController
подклассомViewController
), тогда S объектов (экземпляровMyViewController
) должны иметь возможность заменять там, гдеViewController
ожидается T объектов (экземпляров ).Инициализаторы не наследуются в Swift, если какие-либо инициализаторы явно определены в подклассе. Если один инициализатор указан явно, то должны быть явно предоставлены все остальные (которые затем могут просто вызывать
super.init(...)
). См. Этот вопрос для обоснования. Это на Java, но все еще применяется.Согласно пункту 1, все, что
ViewController
может делать оригинал ,MyViewController
должен уметь делать подкласс. Одна из таких вещей - возможность инициализации из заданногоNSCoder
. По пункту 2 вашMyViewController
подкласс не наследует эту способность автоматически. Таким образом, вы должны вручную указать инициализатор, удовлетворяющий этому требованию. В этом случае вам просто нужно передать полномочия суперклассу, чтобы он делал то, что обычно делал.источник