2013-04-12 4 views
5

Каждый класс вида имеет несколько методов init - те, которые уже включены как часть UIView, а затем дополнительные - и каждый из них устанавливает одинаковые элементы таким же образом. Поэтому у меня обычно есть все, у кого есть метод [self initialSetup];, который включает в себя настройку всех этих элементов.Лучший способ сделать init без повторения кода?

Проблема, с которой я столкнулся, заключается в том, что если подкласс также имеет метод initialSetup, он будет переопределять метод superclass initialSetup, и, таким образом, суперкласс должен быть общедоступным, чтобы все еще функционировать. Это вызывает проблемы с организацией, так как метод никогда не должен вызываться иначе, чем от init, поэтому у него нет оснований быть публичным.

ответ

2

Вы столкнулись с проблемой, что нет идеального решения. То, что вы в идеале имеете, - это метод, который нельзя подклассифицировать в обычном смысле, доступный только для экземпляров этого точного типа класса.

Если это риск, обычной практикой является включение имени класса в метод установки. Итак, вместо initialSetup у вас будет что-то вроде myViewSubclassInitialSetup.

Вы также можете добавить что-то вроде этого в верхней части методы:

NSAssert([self isMemberOfClass:[ThisClass class]], 
      @"IniitalSetup called by sub- or superclass") 

Тогда ваш отладки строит сгенерирует исключение, если подкласс или суперкласс заканчивает вызов метода инициализации. Это даст вам место для точки останова и stacktrace, что позволит вам быстро найти проблему.

Он не добавит никакого кода в ваши версии релиза.

2

Измените имя initialSetup на что-то вроде initialSetupClassName - подклассы, даже если они случайно использовали один и тот же шаблон, не будут использовать то же имя, что и другое имя класса.

Вы также можете использовать префикс «_» для частных методов, которые вы бы скорее не вызывали, но подкласс также может это сделать.

1

Неудовлетворительно Objective C не обеспечивает способ достижения этого «чистым» способом. Идеальное решение было бы защищенным методом. Но это невозможно в Objective C

У Apple была эта проблема, когда они создавали UIGestureRecognizer. Были некоторые методы, которые они действительно не хотели получать от кого-то, но которые должны были быть перезаписаны подклассами. Способ, которым они решили справиться с этим, заключался в создании отдельного файла заголовка (UIGestureRecognizerSubclass.h), который содержит категорию к исходному UIGestureRecognizer с этими «защищенными» методами. Дополнительный заголовок должен быть импортирован только подклассами (т. Е. Для целей подкласса). См. UIGestureRecognizer Class Reference для некоторых деталей.

Конечно, это не мешает кому-либо злоупотреблять дополнительным файлом заголовка, но, по крайней мере, он четко заявляет о своем намерении и хорошо структурирует ваш код. Кроме того, вы не будете «обеспокоены» автозаполнением для дополнительных методов, просто используя класс.

Лично я использую только дополнительный заголовок, если чрезвычайно важно, чтобы никто не вызывал его напрямую. В большинстве случаев я думаю, что использовать общедоступные методы и делать заметки о том, что это такое. В iOS Framework также есть много таких случаев. F.E. многие методы UIViewControllerviewDidLoad и т. д.

2

Похоже, что у вас отсутствует назначенный инициализатор.Назначьте один инициализатор в качестве официального, который фактически выполняет настройку, и все остальные просто называют это с некоторой степенью настройки. Обычно назначенный инициализатор будет самым подробным - например, если у вас есть init, initWithName:, initWithName:age: и initAsFiveYearOldNamed:, назначенный инициализатор будет initWithName:age:, а остальные инициализаторы просто вызовут этот метод с соответствующими аргументами.

Смежные вопросы