Какой инициализатор переопределить для подкласса UITableViewController
У меня есть подкласс UITableViewController
, который создается в зависимости от того, где он используется, в NIB или через код. В обоих случаях я хочу выполнить настройку в методе инициализации. Означает ли это, что мне нужно реализовать как initWithNibName:bundle:
, так и initWithCoder:
, и будет ли каждый метод вызывать его соответствующий супер инициализатор?
Пока мне это не нужно прямо сейчас, что делать, если я также хочу создать экземпляр контроллера представления с помощью initWithStyle:
? Нужно ли мне тогда 3 разных метода init, которые повторяют одно и то же поведение?
Похоже, что это нарушает все назначенное соглашение инициализатора, так как по существу есть 3 отдельных инициализатора, которые в конечном итоге не вызовут обычный метод init. Или есть способ создать общий назначенный инициализатор, поддерживая три разных маршрута-экземпляра?
Ответы
Ответ 1
Моя путаница была основана на ошибочном убеждении, что каждый класс должен иметь один назначенный инициализатор. Это неверно, и в случае UITableViewController
есть 3 назначенных инициализатора (насколько я могу судить):
-
initWithStyle:
объявлен локально
-
initWithNibName:bundle:
унаследовано от UIViewController
-
initWithCoder:
от принятия протокола NSCoding
Вам нужно переопределить 1 или более из них в вашем подклассе в зависимости от того, как создается ваш подкласс. В моем случае мне пришлось реализовать # 2 и # 3, поскольку класс может быть загружен из NIB или создан с помощью кода со ссылкой на NIB. (Я полагаю, что редко можно использовать как initWithStyle:
, так и initWithNibName:bundle:
для одного класса.)
Я нашел Apple Полезные советы по кодированию Cocoa.
Ответ 2
Внутри
- UITableViewController
-initWithStyle:
вызывает супер -init
, затем устанавливает _tableViewStyle
ivar.
- UIViewController
-init
просто вызывает -initWithNibName:bundle:
с аргументами по умолчанию.
- UITableViewController не переопределяет
-initWithNibName:bundle:
.
Поэтому, если вы переопределяете -initWithNibName:bundle:
, тогда -initWithStyle:
тоже примет это изменение. Конечно, чтобы играть безопасно (так как вы не должны полагаться на детали реализации), переопределите их оба.
(И не нужно переопределять -initWithCoder:
, если вы не удалите/архивируете экземпляры.)
Ответ 3
Чтобы уточнить, initWithStyle:
, будучи UITableViewController
, только опубликованный инициализатор в документах, является его единственным явным назначенным инициализатором.
initWithNibName:bundle:
наследуется от UIViewController и является назначенным инициализатором для этого класса. Таким образом, в соответствии с рекомендациями Cocoa UITableViewController
должен переопределить этот метод (путем его реализации). Однако это не делает его назначенным инициализатором UITableViewController
.
initWithCoder:
, как вы указываете, является неявным назначенным инициализатором из NSCoding
.
Ответ 4
Реализовать:
- (void) viewDidLoad
и выполните инициализацию вашего компонента.
Преимущество имеет только выполнение инициализации, когда запрос действительно запрашивается.
Или просто создайте отдельный метод установки, который вызывается всеми инициализаторами.
Ответ 5
Добавление к сообщениям выше этой ссылки -initWithCoder:
Если вы добавили контроллер представления к своему родителю через построитель интерфейса (например: если контроллер представления подключен к контроллеру панели вкладок в построителе интерфейса), вам необходимо переопределить -initWithCoder.
(- initWithNibName будет вызываться только при программном программировании контроллера вида.)