Как использовать NS_DESIGNATED_INITIALIZER и переопределить init?

Ладно, это, по общему признанию, вопрос с лучшей практикой, но я хочу, чтобы все было правильно, поэтому, надеюсь, кто-то может просветить меня:

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

Чтобы избавиться от предупреждения, я добавил init как второй назначенный инитализатор в расширение моего класса, например:

 @interface MyClassName () // some other stuff not relevant` -(nullable instancetype)init NS_DESIGNATED_INITIALIZER; @end 

Теперь я могу просто return nil; в методе overriden init как я хотел. Это означает, что моя документация (я использую appledoc) и расширение кода расширения XCode не скажет кому-то, использующему мою инфраструктуру, что init на самом деле также назначенный инициализатор (поэтому они не будут случайно использовать его), но он все еще существует ( например, в модульных тестах это может пригодиться).

Мой вопрос: есть ли какие-либо опасности для этого, кроме того, что кто-то действительно использует его в производстве, радостно отправляя сообщения в ноль после этого, не понимая? Будет ли это одним из немногих случаев, когда предпочтительным было бы исключение исключения в init?

Вместо того, чтобы просто возвращать nil из init (и, возможно, добавить комментарий, говорящий, что вы не должны его называть), вы должны пометить его как недоступный.

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

Для этого вы можете использовать макрос NS_UNAVAILABLE или использовать недоступный __attribute__ как показано в этом ответе . Преимущество использования __attribute__ заключается в том, что вы можете указать сообщение, которое компилятор представит пользователю.

Например:

 @interface Foo : NSObject -(instancetype) init __attribute__((unavailable("You cannot create a foo instance through init - please use initWithBar:"))); -(instancetype) initWithBar:(Bar*)bar NS_DESIGNATED_INITIALIZER; @end ... Foo* fooA = [[Foo alloc] init]; // ERROR: 'init' is unavailable: You cannot create a foo instance through init - please use initWithBar: Foo* fooB = [[Foo alloc] initWithBar:[[Bar alloc] init]]; // No error 
  • Как скопировать код в SVN из xcode 6.4?
  • iOS симулятор с подключением к Интернету
  • Есть ли способ сообщить об ошибках в документации Apple?
  • Универсальные ссылки на macOS
  • Являются ли Xcode 4 и iOS SDK 4.3 совместимыми со Snow Leopard?
  • ARC - Значение __unsafe_unretained?
  • Как создать резервную копию ботов OS X Server
  • Карфаген: Как получить самую последнюю версию данного репозитория?
  • Уникальные атрибуты Core Data в iOS и Mac OS
  • Как определить сильное свойство IBOutlet в Swift?
  • Подавлять предупреждения Valgrind от iOS SDK
  • Interesting Posts

    «Назначить контакт» в UIActivityViewController не работает …!

    Профилировщик говорит мне, что сравнение с нолем медленное

    Как копировать объекты массива, которые находятся в разных вкладках

    Пролонгировать анимацию UIPickerView

    В чем причина того, что WatchKit2 код ошибки 7007 «сеанс на сопряженном устройстве недоступен»

    Добавление AVCaptureDeviceInput в CaptureSession сбрасывает / перенаправляет видео

    iPhone-Twitter API GET Пользователи Последователи / После

    Использует ли PhoneGap только UIWebVIew или делает что-то большее? Nitro?

    Как сохранить аудиофайл после записи локально или firebase в объективе c?

    Получение xmpp_login Ток доступа не работает в Facebook iOS SDK

    Ошибка Apple MDM, но только для некоторых устройств iOS

    Не удается выполнить единичный тест на устройстве – Сбой генерации кода покрытия (IOS)

    wait_fences: не удалось получить ответ: 10004003?

    Сбой происходит на iOS 5

    iOS 8 SDK: модальный интерфейс UIWebView и камера / подборщик изображений

    Давайте будем гением компьютера.