Obj-, переменная экземпляра, используемая, когда ‘self’ не задан в качестве результата ‘[(super или self) инициализации …]’

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

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

Вопрос:

Я уже задавал аналогичный вопрос к этому, но я все еще не вижу проблемы?

 -(id)initWithKeyPadType: (int)value
{
    [self setKeyPadType:value];
    self = [self init];
    if( self != nil )
    {
        //self.intKeyPadType = value;

    }
    return self;
}

- (id)init {

    NSNumberFormatter *formatter = [[[NSNumberFormatter alloc] init] 
                                                              autorelease];
    decimalSymbol = [formatter decimalSeparator];
....
  

Предупреждение приходит из строки выше Instance variable used while 'self' is not set to the result of '[(super or self) init...]'

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

1. если я правильно понимаю ваш код, вы используете переменную перед вызовом [super init], и это может испортить распределение памяти

2. Он нигде не вызывает super init

Ответ №1:

То, что вы пытаетесь сделать, технически нормально, но на каком-то этапе вам нужно вызвать [super init] . Если init метод вашего класса выполняет множество обычных инициализаций, которые используют другие initWith... методы, тогда поместите туда свой [super init] . Кроме того, всегда проверяйте, что класс был init улучшен, прежде чем пытаться играть с переменными экземпляра.

 - (id) initWithKeyPadType: (int)value
{
    self = [self init]; // invoke common initialisation
    if( self != nil )
    {
        [self setKeyPadType:value];
    }
    return self;
}

- (id) init
{
    self = [super init]; // invoke NSObject initialisation (or whoever superclass is)
    if (!self) return nil;

    NSNumberFormatter *formatter = [[[NSNumberFormatter alloc] init] 
                                                          autorelease];
    decimalSymbol = [formatter decimalSeparator];

    ...
  

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

1. Можете ли вы подробнее рассказать о фактическом риске, на который указывает предупреждение GCC? Предполагая, что обнуление памяти объекта происходит во время выделения (что, я считаю, правильно), кажется, что только @public или @protected ivar будут подвержены риску быть заблокированными init методом суперкласса, что требует предупреждения. Я не могу придумать, почему предупреждение было бы полезно для частного ivar, за исключением стилистического, но это обычно не забота компилятора.

2. @quixoto: alloc обнуляет память. Я тоже понятия не имею, почему это важно… Это может иметь какое-то отношение к тому факту, что вызов [super init] может вернуть nil , и если это произойдет, то все [sub init] методы также должны вернуть nil . Кроме этого, я бы понятия не имел, почему GCC это волнует.

Ответ №2:

Предупреждение означает то, что оно говорит. Вы присваиваете что-то decimalSymbol , являющееся переменной экземпляра, но в этот момент экземпляра нет. Вам нужен

 self = [super init];
  

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

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

1. Слишком сильно говорить «экземпляра нет». alloc должен был уже быть создан экземпляр. Проблема в том, что экземпляр, возможно, был неправильно инициализирован (поскольку это то, что init делает).