Можно ли написать initn-annotation в init?

Теперь в objective-c есть две новые аннотации: nonnull и с нулевым значением.
Какой из них я должен использовать для спецификации типа возвращаемого значения метода init?

- (instancetype)init {
    if (self = [super init]) {
        // ...
    }
}

Голос для с нулевым значением:
Существует "если", чтобы проверить, что возвращает [super init], и нет гарантии, что он никогда не вернет нуль.

Голос для nonnull:
Я не знаю реальных случаев, когда init возвращает nil, и я никогда не проверяю его.

Ответ 1

  • Для произвольного класса, документы для -init:

    Возвращаемое значение: инициализированный объект или nil, если по какой-то причине невозможно создать объект, который не привел бы к исключению.

Метод случайного класса init может возвращать nil. Если вы возвращаете результат [super init] из подкласса этого класса, есть вероятность, что return будет nil. Ваш класс должен соответствующим образом аннотировать свой метод init как nullable, если он возвращает результат с нулевым значением [super init].

Каждая конкретная реализация суперкласса init должна быть проверена, чтобы определить, может ли вызов подкласса [super init] или не возвращать nil по очереди.

Это означало бы, что аннотация вашего метода должна быть nullable, если вы не подтвердили, что результат [super init] будет не be nil.

  • Для прямых подклассов NSObject, в частности:

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

Таким образом, для классов, наследующих непосредственно из NSObject, -init может быть помечен как nonnull.

  • Если ваш класс возвращает nil

Возможно, результат [super init] равен nonnull, но реализация вашего класса init возвращает nil в ответ на какое-то другое условие.

- (instancetype)init {
    if (self = [super init]) { // nonnull

        if (someFailureCondition) {
            return nil; // nullable
        }

    }

    return self;
}

В этом случае ваша реализация должна, конечно, быть аннотирована nullable.

Ответ 2

Можно предположить, что [[NSObject alloc] init] никогда не завершится. Вот что на самом деле говорит документация:

Метод init, определенный в классе NSObject, не инициализирует; он просто возвращает себя. В терминах недействительности вызывающие могут предположить, что реализация NSObject init не возвращает nil.

Ссылка: https://developer.apple.com/reference/objectivec/nsobject/1418641-init?language=objc