Подтвердить что ты не робот

Что такое init coder aDecoder?

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

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

    }

Почему именно мне всегда нужно это называть? Что оно делает? Могу ли я поместить свойства внутри init?

4b9b3361

Ответ 1

Я начну этот ответ с противоположного направления: что, если вы хотите сохранить состояние своего вида на диск? Это называется сериализацией. Обратное - десериализация - восстановление состояния объекта с диска.

Протокол NSCoding определяет два метода сериализации и десериализации объектов:

encodeWithCoder(_ aCoder: NSCoder) {
    // Serialize your object here
}

init(coder aDecoder: NSCoder) {
    // Deserialize your object here
}

Так зачем это нужно в вашем пользовательском классе? Ответ - Interface Builder. Когда вы перетаскиваете объект на раскадровку и настраиваете его, Interface Builder сериализует состояние этого объекта на диске, а затем десериализует его, когда раскадровка появляется на экране. Вы должны сказать Interface Builder, как это сделать. По крайней мере, если вы не добавляете никаких новых свойств в свой подкласс, вы можете просто попросить суперкласс выполнить упаковку и распаковку для вас, следовательно, вызов super.init(coder: aDecoder). Если ваш подкласс более сложный, вам нужно добавить свой собственный код сериализации и десериализации для подкласса.

Это отличается от подхода Visual Studio, который заключается в том, чтобы писать код в скрытый файл, чтобы сделать объект во время выполнения.

Ответ 2

Требование реализовать этот инициализатор является следствием двух вещей:

  • Принцип подстановки Лискова. Если S является подклассом T (например, MyViewController является подклассом ViewController), то S-объекты (экземпляры MyViewController) должны быть в состоянии быть заменены там, где ожидаются объекты T (экземпляры ViewController)).

  • Инициализаторы не наследуются в Swift, если какие-либо инициализаторы явно определены в подклассе. Если один инициализатор явно указан, тогда все остальные должны быть явно предоставлены (которые затем могут просто вызвать super.init(...)). См. этот вопрос для обоснования. Это в Java, но все же применяется.

В пункте 1 все, что может сделать исходный ViewController, должен выполняться подкласс MyViewController. Одной из таких вещей является возможность инициализации из заданного NSCoder. В пункте 2 ваш подкласс MyViewController не наследует эту способность автоматически. Таким образом, вы должны вручную предоставить инициализатор, который выполняет это требование. В этом случае вам просто нужно делегировать до суперкласса, чтобы он выполнял то, что обычно делал.