Почему аутлет не может быть инициализирован в initWithCoder? - PullRequest
0 голосов
/ 06 сентября 2018

Мы все знаем, что как только мы опускаем розетку внутри View или его ViewController, он помечается как развернутый, и мы все знаем, что Swift хочет инициализировать все свойства в фазе инициализации, и это предложение мы даем тот, кто спрашивает нас впервые, почему в компании всегда есть точка с восклицательным знаком.

Сегодня я пытался понять, почему объект, который приходит из XIB, не может быть инициализирован в методе initWithCoder:.

Насколько я знаю, файл XIB просто содержит всю информацию об объектах, нарисованных внутри XIB с использованием структуры файла XML. Поэтому то, что мы видим внутри файла XIB, будет заархивировано и сохранено в файл.

Когда мы вызовем метод класса UINib loadNibNamed:owner:options:, он разархивирует ранее созданный объект, найдет все свойства, установит их и отправит объекту awakeFromNib объекту ...

но из-за того восклицательного знака, который говорит: «На этапе инициализации я не могу инициировать вас», то, что я сказал выше, должно быть неверным. Но почему? Может кто-нибудь сказать мне, почему Nib не может быть инициализирован и должен быть помечен как необязательный?

Здесь у меня есть несколько документов от Apple, которые мне не помогли https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html

1 Ответ

0 голосов
/ 06 сентября 2018

Ваши @IBOutlet свойства представлены вашим подклассом UIViewController.

Сказать, что «Swift хочет инициализировать все свойства в фазе инициализации», немного упрощает.

Правила инициализации Swift гласят, что все свойства, представленные подклассом, должны быть инициализированы перед вызовом инициализатора суперкласса, и компилятор Swift должен иметь возможность «видеть» эту инициализацию; должно быть явное присваивание. Это «Проверка безопасности 1»: -

Проверка безопасности 1

Назначенный инициализатор должен убедиться, что все свойства, представленные его классом, инициализированы до его делегирования инициализатору суперкласса.

Почти во всех случаях, когда вы используете сцену XIB или раскадровку, вы не переопределяете init(coder:), поэтому компилятор может определить, что вы не указали явно значения для этих свойств.

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

Неявно развернутый необязательный параметр не говорит: «На этапе инициализации я не могу вас инициализировать»; Это больше похоже на «Я знаю, что похоже, что это не инициализируется, но во время выполнения это будет. Поверьте мне» (Строго говоря, это просто объявление необязательного значения, которое может быть nil, поэтому компилятор не не жалуйтесь, что оно не инициализировано, но неявно принудительно разворачивает свойство всякий раз, когда на него ссылаются - отсюда и название «неявно развернутый необязательный»).

Это работает в течение @IBOutlet с, поскольку в процессе загрузки используется Код значения ключа для назначения значений во время выполнения.

По этой причине, если вы удалите @IBOutlet, но забудете обновить XIB / Storyboard, вы получите исключение времени выполнения, сообщающее, что ваш класс "не соответствует ключу / значению для xxx".

Использование неявно развернутых опций таким образом, как правило, считается приемлемым, так как вы довольно быстро узнаете, возникла ли у вас проблема с подключением во время тестирования (поскольку ваше приложение вылетает с «неожиданно нулевым значением»), и это экономит много условного развертывания.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...