Цель-C: Слабый attritube не работает должным образом
Возможный дубликат:
Почему слабые свойства NSString не выпускаются в iOS?
Я новичок в Objective C, и у меня есть несколько вопросов, на которые я не могу ответить сам. У меня есть блок кода для тестирования переменной __weak (я, конечно, использую ARC):
NSString *myString = [[NSString alloc] initWithFormat:@"John"];
NSString * __weak weakString = myString;
myString = nil; //<-- release the NSString object
NSLog(@"string: %@", weakString);
Вывод вышеприведенных кодов является ожидаемым, поскольку слабая строка является слабой переменной:
2013-01-02 11:42:27.481 ConsoleApp[836:303] string: (null)
Но когда я изменил код к этому:
NSString *myString = [[NSString alloc] initWithFormat:@"John"];
NSString * __weak weakString = myString;
NSLog(@"Before: %@", weakString); //<--- output to see if the __weak variable really works.
myString = nil;
NSLog(@"After: %@", weakString);
Результат совершенно не тот, который я ожидал:
2013-01-02 11:46:03.790 ConsoleApp[863:303] Before: John
2013-01-02 11:46:03.792 ConsoleApp[863:303] After: John
Вывод последнего NSLog должен был быть (ноль) вместо "Джон". Я пытался найти во многих документах, но я не нашел ответ по этому делу. Может ли кто-нибудь дать разумное объяснение? Заранее спасибо.
2 ответа
NSLog
функция сохраняет переданную строку NSString в пуле авто-релиза. Поэтому переменная обнуления не будет обнуляться до тех пор, пока не будет истощен пул автоиздания. Например:
__weak NSString* weakString = nil;
@autoreleasepool {
NSString* myString = [[NSString alloc] initWithFormat:@"Foo"]; // Retain count 1
weakString = myString; // Retain count 1
NSLog(@"A: %@", weakString); // Retain count 2
NSLog(@"B: %@", weakString); // Retain count 3
myString = nil; // Retain count 2
NSLog(@"C: %@", weakString); // Retain count 3
NSAssert(weakString != nil, @"weakString is kept alive by the autorelease pool");
}
// retain count 0
NSAssert(weakString == nil, @"Autorelease pool has drained.");
Почему NSLog помещает строку в пул авто-релиза? Это деталь реализации.
Вы можете использовать отладчик или инструменты, чтобы следить за счетом сохранения экземпляра NSString. Точные значения сохранения не важны, но они проливают некоторый свет на то, что происходит за кулисами. Что важно, так это то, что экземпляр NSString освобождается при сливе пула автоматического выпуска.
Я думаю, что это просто некоторые детали реализации. Ваша слабая переменная очищается, но не сразу. Например, это работает как ожидалось:
NSString *myString = [[NSString alloc] initWithFormat:@"John"];
NSString * __weak weakString = myString;
@autoreleasepool {
NSLog(@"Before: %@", weakString);
myString = nil;
}
NSLog(@"After: %@", weakString); // nil