__block
является классификатором хранения. Он указывает, что переменная должна быть непосредственно захвачена блоком, а не копированием. Это полезно в случае, если вам необходимо изменить исходную переменную, как показано в следующем примере
__block NSString *aString = @"Hey!";
void(^aBlock)() = ^{ aString = @"Hello!" }; // without __block you couldn't modify aString
NSLog(@"%@", aString); // Hey!
aBlock();
NSLog(@"%@", aString); // Hello!
В АРК это вызывает переменная будет автоматически сохранена, так что его можно смело ссылаться в рамках реализации блока. В предыдущем примере затем aString
отправляется сообщение retain
при захвате в контексте блока.
Не то, чтобы это не подтвердилось в MRC (Manual Reference Counting), где переменная указана без сохранения.
Отметить его как __weak
, чтобы переменная не сохранялась, поэтому блок непосредственно ссылается на нее, но не сохраняет ее. Это потенциально опасно, поскольку в случае, если блок живет дольше, чем переменная, поскольку он будет ссылаться на память мусора (и может произойти сбой).
Вот соответствующий пункт из clang doc:
В Objective-C и языках Objective-C++, мы допускаем __weak
спецификатор для __block
переменных типа объекта. [...] Этот определитель заставляет эти переменные сохраняться без сохранения отправляемых сообщений. Это заведомо приводит к висящим указателям, если Блок (или копия) выделяет время жизни этого объекта.
Наконец, утверждение, что __block
может использоваться для исключения сильных ссылочных циклов (так называемых циклов удержания), совершенно неверно в контексте ARC. В связи с тем, что в ARC __block
заставляет переменную сильно ссылаться, это, скорее всего, вызывает их.
Например, в MRC этот код разбивает сохранить цикл
__block typeof(self) blockSelf = self; //this would retain self in ARC!
[self methodThatTakesABlock:^ {
[blockSelf doSomething];
}];
а для достижения такого же результата в АРК, обычно не делают
__weak typeof(self) weakSelf = self;
[self methodThatTakesABlock:^ {
[weakSelf doSomething];
}];
Нет это, вероятно, говорит «' __weak' используется для избегайте удерживать циклы ». – trojanfoe
На самом деле один из ответов (подтвержденный, но не принимаемый) говорит: «' __block' иногда используется, чтобы избежать циклов сохранения » – Adam
Я этого не понимаю; использование '__weak' - это способ избежать этого. – trojanfoe