4

Рассмотрим следующие два случая:Когда слабая ссылка обновляется до нуля в Objective-C?

// case 1 
NSObject *strongOne = [[NSObject alloc] init]; 
NSObject * __weak weakOne = strongOne; 

if (weakOne) { 
    NSLog(@"weakOne is not nil."); 
} else { 
    NSLog(@"weakOne is nil."); 
} 

strongOne = nil; 

if (weakOne) { 
    NSLog(@"weakOne is not nil."); 
} else { 
    NSLog(@"weakOne is nil."); 
} 

Выходы это:

weakOne is not nil. 
weakOne is not nil. 

И

// case 2 
NSObject *strongOne = [[NSObject alloc] init]; 
NSObject * __weak weakOne = strongOne; 

strongOne = nil; 

if (weakOne) { 
    NSLog(@"weakOne is not nil."); 
} else { 
    NSLog(@"weakOne is nil."); 
} 

Выходы это:

weakOne is nil. 

Насколько Я знаю, когда strongOne освобождается, слабая ссылка на тот же объект должна быть обновлена ​​до nil.

Мой вопрос: Почему это происходит только в case 2?

+0

Вы также должны проверить это с помощью Release-build вместо Debug. Результат может быть другим ... –

ответ

1

Я думаю, это связано с тем, что, когда вы попадаете в оператор if с помощью weakOne, вы увеличиваете количество удержаний в пуле автозапуска; поэтому слабый указатель не будет равен нулю до тех пор, пока пул авторезистов не будет слит.

// Try this 
NSObject *strongOne = [[NSObject alloc] init]; 
NSObject * __weak weakOne = strongOne; //count 1 
@autoreleasepool { 

    if (weakOne) { 
     NSLog(@"weakOne is not nil."); //count 2 
    } else { 
     NSLog(@"weakOne is nil."); 
    } 

    strongOne = nil; // count 1 

    if (weakOne) { 
     NSLog(@"weakOne is not nil."); 
    } else { 
     NSLog(@"weakOne is nil."); 
    } 

} // count 0, therefore the weakOne become nil 

if (weakOne) { 
    NSLog(@"weakOne is not nil."); 
} else { 
    NSLog(@"weakOne is nil."); 
} 
1

Насколько я знаю, когда strongOne освобождается, слабая ссылка на тот же объект должен быть обновлен до нуля.

Это верно. Но вы не освобождаете объект, когда вы устанавливаете strongOne в ноль, вы просто меняете указатель. ARC, вероятно, вызывает autorelease на объекте strongOne указывает на то, что объект фактически не будет освобожден до тех пор, пока не будет сброшен пул авторезистов.

Почему это происходит только в случае 2?

Похоже, что ARC отправляет release в таком случае, поэтому объект освобождается и ваш слабый справочник обновляется сразу же.

Возможно, компилятор замечает, что вы никогда не использовали strongOne, прежде чем устанавливать его на ноль, за исключением того, чтобы назначить его слабкому указателю и поэтому решает не выделять объект в первую очередь. Пройдите этот код и посмотрите, получает ли значение strongOne значение, отличное от нуля.