Это хороший вопрос. И ответ при использовании ARC
заключается в том, что сам блок сохраняет объект, так что он будет примерно позже. Это одна из тех тонких ошибок памяти. Если UITableView
, из которого поступает эта ячейка, освобождается и освобождает все ее ячейки, эта ячейка будет сохранена (хотя и за пределами экрана) и будет иметь присвоение cell.imageView = image;
, тогда она будет освобождена.
Я большой поклонник контролируемых экспериментов и намеревался проверить это, но у UITableView
есть много движущихся частей (не каламбур). Поэтому я создал очень простой эксперимент, используя простой подкласс NSObject
следующим образом:
@implementation SayHello
-(void)sayHello{
NSLog(@"Hello");
}
-(void)dealloc{
NSLog(@"SayHello dead");
}
@end
Очевидно, этот класс предназначен для того, чтобы дать мне функцию для вызова в блоке (sayHello
) и будет производить NSLog
при отмене выделения.
Я провел свой тест так:
SayHello *hello = [[SayHello alloc] init];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
double delayInSeconds = 30.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[hello sayHello];
});
});
30 секунд дают даже самое ленивое время цикла выполнения, чтобы освободить «привет» объект (если, на самом деле, он не был сохранен). Но в течение этих 30 секунд консоль молчит. По истечении 30 секунд я немедленно получаю сообщение «Hello», а затем сообщение «SayHello dead».
Так как же это "готча"? Что ж, очевидно, если вы не понимаете, что Blocks / ARC делают это, это может закончиться тем, что вы не захотите. Но также с вашим примером UITableViewCell
; что если ваша ячейка отображается один раз и отправляет запрос по сети на изображение, но пока блок ожидает изображение, ячейка используется повторно? Теперь есть второй блок со ссылкой на эту ячейку, пытающийся установить ее изображение. Что ж, теперь у вас есть гонка, в которой проигравший будет решать, какое изображение будет отображаться.