Несколько вопросов о переопределении функции инициализации

#iphone #objective-c #xcode #initialization

#iPhone #objective-c #xcode #инициализация

Вопрос:

Как новичок в Objective-C, я очень смущен функцией init, а также тем, как и когда ее переопределять. Итак, вот несколько вопросов :

  • По-видимому, это работает нормально, когда функция инициализации не переопределена, так что это просто хорошая практика для этого? Если это так, то очень ли плохая практика не делать этого?
  • Давайте предположим, что я переопределяю функцию, потому что мне нужно присвоить переменной значение по умолчанию. Должен ли я выделять и инициализировать все остальные ivar, включая IBOutlets?

Пожалуйста, обратите внимание, что я знаком с синтаксисом :

 if ((self = [super init]))
{
    _foo = [[Bar alloc] init];
}
return self;
  

Ответ №1:

Согласно «Инициализации»:

Класс обычно реализует инициализатор для своих объектов, но это не обязательно. Если класс не реализует инициализатор, Cocoa вызывает инициализатор ближайшего предка класса. Однако подклассы часто определяют свой собственный инициализатор или переопределяют инициализатор своего суперкласса для добавления специфичных для класса инициализаций. Если класс реализует инициализатор, он должен вызвать инициализатор своего суперкласса в качестве первого шага. Это требование обеспечивает серию инициализаций для объекта по цепочке наследования, начиная с корневого объекта. NSObject Класс объявляет init метод в качестве инициализатора объекта по умолчанию, поэтому он всегда вызывается последним, но возвращается первым.

Как говорится, вы переопределяете назначенный инициализатор вашего суперкласса, когда вам нужно выполнить некоторую инициализацию после завершения ее инициализации. Не нужно этого делать? Тогда вам не нужно переопределять.

Когда ваш объект создается из кончика, -init не вызывается. Вместо этого ваш вновь выделенный объект получит сообщение -initWithCoder: or -initWithFrame: в зависимости от типа объекта. Процесс загрузки NIB отправляет ваш объект -awakeFromNib после того, как он и все другие объекты, созданные NIB, на которые он ссылается, были установлены. Это позволяет избежать переопределения -initWithCoder: / -initWithFrame: , когда вы хотите выполнить некоторую настройку после загрузки NIB. Если вы можете сделать то, что хотите, путем переопределения -awakeFromNib , а не инициализатора, вам следует это сделать.

Смотрите также «Множественные инициализаторы», в котором объясняется концепция «назначенного инициализатора» и то, как разные классы могут иметь разные назначенные инициализаторы, и «Выделение и инициализация объектов» для менее понятного, но более подробного описания соглашений о выделении и инициализации, принятых Objective-C.

Комментарии:

1. Спасибо за объяснение! Теперь это имеет гораздо больше смысла для меня.

2. На самом деле, у меня все еще есть один вопрос. Давайте рассмотрим, что экземпляр объекта создается не из NIB, и что вам действительно нужно выполнить инициализацию для конкретного класса — например, у вас есть десять ivar, и вы просто хотите присвоить @"foo" ivar с именем _foo . Обязательно ли обрабатывать все переменные при переопределении init или вы можете просто присвоить значение по умолчанию _foo ? Более того, если вам действительно нужно обработать все переменные, можете ли вы просто присвоить им nil или вам нужно написать alloc / init для всех них?

3. alloc возвращает память, заполненную нулем. Обычно нет причин назначать NO or nil или что-то подобное ivar во время инициализации, если только вам не нужно отменить что-то, сделанное инициализатором суперкласса.

Ответ №2:

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

Вам не нужно (и не следует) выделять или инициализировать IBOutlets . Objective-C автоматически инициализирует все переменные экземпляра, включая IBOutlets значение 0 ( nil ).

Ответ №3:

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