Obj-C, возвращающий ‘self’, пока для него не установлен результат ‘[(super или self) init …]’?

#objective-c #xcode #cocoa-touch #analyzer

#objective-c #xcode #cocoa-touch #анализатор

Вопрос:

После обновления я получаю предупреждение анализатора…

Returning 'self' while it is not set to the result of '[(super or self) init...]'

Не знаю, что с этим не так?

 - (id)initWithFrame:(CGRect)frame {
    if (self == [super initWithFrame:frame]) {
        [self initLayers];
    }
    return self;
}
  

Ответ №1:

Избавьтесь от второго знака равенства. Правильное if утверждение является:

 if(self = [super initWithFrame:frame])
  

Смысл этого в том, что реализация super может возвращать другой, но все еще действительный объект, отличный от текущего значения self . В этом случае ваше утверждение if будет ложным, поскольку объекты разные, и поэтому ваша инициализация не произойдет. Однако, поскольку он вернул другой объект, реализация super должна была освободить старый self, который вы возвращаете. Это означает, что вы, вероятно, возвращаете недопустимый указатель.

Используя только один знак равенства, вы устанавливаете переменную вместо ее сравнения. Поскольку if(object) имеет значение true, если object не nil , это эквивалентно этому:

 if((self = [super initWithFrame:frame]) != nil)
  

Или, более простая для понимания версия:

 self = [super initWithFrame:frame];
if(self != nil)
  

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

 // good
id object = [[MyClass alloc] init];
// bad
id object = [MyClass alloc];
[object init];
  

Ответ №2:

Если я правильно помню, синтаксис self = ... не self == ... . Синтаксис использует возвращаемое значение из присваивания.

Ответ №3:

ваш возвращаемый self не инициализирован

 - (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self initLayers];
    }
    return self;
}
  

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

1. Вы должны присвоить результат [super init] для self. В вашем фрагменте вы используете «==», который является всего лишь сравнением, а не оператором присваивания.