В ARC, блок, как предполагается, вызывает цикл сохранения, если вы используете, например, self
внутри блока.
Я видел обходной путь здесь ,например:
Как этот обходной путь может предотвратить цикл сохранения?
weakRequest
- это просто указатель на точно такой же объект, на который ссылается request
.Когда ARC изменяет счет сохранения weakRequest
или request
, он воздействует на тот же объект.
Затем в блоке происходит странная вещь:
__strong ASIHTTPRequest *strongRequest = weakRequest;
Это эквивалентно высказыванию:
ASIHTTPRequest *strongRequest = weakRequest;
[strongRequest retain];
Но опять же: это один и тот же объект.Почему все эти разные имена переменных?Они просто указатели!
Я никогда особо не заботился о блоках и старался их избегать.Но теперь мне стало интересно, о чем все говорят, когда говорят «блок захватывает переменные».До сегодняшнего дня я думал, что это просто означает, что блок будет сохранять каждый используемый вами указатель, который был определен вне области действия блока, а это означает, что блок просто сохраняет любой объект, к которому вы прикоснулись, в своей области.
Я сделал этобыстрый тест:
UIView *v = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
[self.view addSubview:v];
v.backgroundColor = [UIColor orangeColor];
NSLog(@"self = %p", self); // 0x6a12a40
[UIView animateWithDuration:1.5
delay:0
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
UIViewController *my = self;
NSLog(@"my = %p", my); // 0x6a12a40
v.frame = CGRectMake(200, 200, 100, 100);
}
completion:nil];
Как вы видите, сам объект остается точно таким же.Блок не создает копию.Таким образом, я могу с уверенностью предположить, что все годы знания C и Objective-C все еще действительны:
ASIHTTPRequest *strongRequest = internetRequest;
ASIHTTPRequest *foo = strongRequest;
ASIHTTPRequest *bar = foo;
if (bar == internetRequest) {
NSLog(@"exact same thing, of course");
}
Так что там происходит?Как это может разрешить сохранение счета, если все, что происходит, это создать разные указатели на один и тот же объект?Почему дополнительная миля создания этих указателей?
Разве это не одно и то же?
[request setCompletionBlock:^{
NSString *respondeString = [request responseString];
if ([_delegate respondsToSelector:@selector(pingSuccessful:)]) {
[_delegate pingSuccessful:responseString];
}
}];
В Objective-C должен быть какой-то секрет, объясняющий, почему дублирование указателей решает проблемы управления памятью здесь.Это просто не имеет никакого смысла для меня.