2015-07-08 3 views
8

Я читал сообщения о сильных/слабых self, чтобы сломать циклы удержания, но я все еще смущен относительно того, как они работают. Я понимаю использование __weak typeof(self) weakSelf = self, чтобы создать слабую ссылку на себя, но я смущен сильной ссылкой. Насколько я понимаю, сильная ссылка заключается в том, что существует сильная ссылка на self, чтобы она не была освобождена до конца блока вправо? Так почему же необходимо иметь __strong typeof(self) strongSelf = weakSelf? Разве это в конечном итоге не указывает на самообъект? Так почему бы не просто strongSelf = self? неПрерывание цикла сохранения с сильным/слабым явлением

ответ

10

Любой не слабый объект, который вы ссылаетесь внутри блока, приведет к неявному сохранению этого объекта при создании блока. Не выполнено, но создано.

Если вы инициализировали внутренний strongSelf непосредственно из себя, вы сохраните значение self и потенциально вызовите цикл сохранения.

С другой стороны, если вы инициализируете его из weakSelf, вы будете не сохранить значение weakSelf.

Это причина двухступенчатой. Внешний код копирует значение self в weakSelf, но ARC не добавляет сохранение, потому что это __weak().

Блок «создание» копирует значение weakSelf (или, по крайней мере, позволяет его значение доступно во время выполнения). Вы не можете видеть, где он копировал его, но это произошло.

В блоке «исполнение» время копирует «значение weakSelf» (которое будет равно nil, если self было отменено в среднее время) в strongSelf, который ARC затем применяет сохранение. Таким образом, для продолжительности блока объект, на который ссылается strongSelf, останется живым, если он будет активным. Если бы вы только полагались на weakSelf, он мог бы пойти ник в любое время во время выполнения блока.

Обратите внимание, что слабый/сильный рисунок - это пояс и фигурные скобки. Многие примеры фактически полагаются на то, что слабый сам пойдет на ноль, и блок будет бесшумно превращаться в коллекцию no-ops (сообщений в ноль).

Сохраняемые циклы обычно возникают только в том случае, если (a) вы сохраняете ссылку на блок в self.property или (b) отдаете блок на какой-либо другой объект (менеджер уведомлений и т. Д.) И указываете, что другой объект забыть об этом в своем dealloc; в обоих случаях ваш dealloc никогда не будет вызываться, пока блок жив.

Когда люди говорят: «Способ сделать этот материал со слабым/сильным рисунком», они принимают худший возможный сценарий.

+0

Ой, так что 'weakSelf = self' присваивает' weakSelf' копию 'self'? Это кажется немного странным, я думал, что он указал на оригинальное «я». заключается в том, что из-за блока или в том, как работает переменное присваивание? – somtingwong

+0

@ user1813076 - Нет, 'weakSelf = self' does _not_ присваивает' weakSelf' копию 'self'. 'WeakSelf' является указателем на' self', указателем, который он устанавливает на 'nil', когда' self' освобождается. – Rob

+0

Этому не помогает скрытая природа замыканий и переменная область. Это фактическая переменная «weakSelf», которая по существу копируется, а не объект, на который она указывает. –

0

Простых слов

__weak TypeOf (сам) weakSelf = самостоятельно - мы используем это как раз перед блоком,

Это просто указатель на себя, не сохраняет цикл начался

- Сохранение будет выполнено тогда и только тогда, когда будет выполнен блок

-> Если мы сделаем это сильным, он начнет удерживать цикл и будет потреблять память, даже если мы не вызываем блок

9

Узор:

__weak typeof(self) weakSelf = self; 

[manager someAsynchronousMethodWithCompletionHandler:^{ 
    typeof(self) strongSelf = weakSelf; 
    if (strongSelf) { 
     ... 
    } 
}]; 

Идея заключается в том, что блок обработчика завершения будет иметь только слабую ссылку на self, так что если self отпущена до блок завершения называется, то это будет безопасно освобождаться потому что блок не имеет сильной ссылки на него. (Общий пример: когда контроллер представления инициирует некоторый асинхронный сетевой запрос для обновления представления, если контроллер представления отклонен до завершения сетевого запроса, нет смысла висеть на экземпляре контроллера просмотра для давно исчезнувшего представления.)

Но это weakSelf/strongSelf модель также гарантирует, что если происходит обратная, что блок завершения начала и встречает strongSelf строку перед self отпущены, блок будет гарантировать, что self сохраняется на протяжении управления этот блок (т.е. он не может быть освобожден на полпути через запуск блока завершения, даже если он работает в другом потоке). Это имеет ряд потенциальных преимуществ (от целостности объекта до устранения условий гонки). Иногда вам фактически не нужна strongSelf половина «weakSelf/strongSelf танец», но это бесценный инструмент, когда это необходимо.

Если, однако, вы имели линию внутри блока, который сказал, typeof(self) strongSelf = self (вместо weakSelf), простое присутствие self в правой части этого заявления приведет к блоку сохранения сильной ссылки на self фронт , полностью побеждая цель использования weakSelf.

+3

Я не думаю, что у вас есть правильный рисунок. Внутреннее назначение сильного Себя от себя должно быть от слабого. –

+0

Это должно быть 'typeof (self) strongSelf = weakSelf;' внутри этого блока. – JaredH

+0

Lol. Совершенно верно. Исправлена. – Rob

1

Есть правильные ответы, но я действительно не знаю, являются ли они ответы на ваш Q. Они объясняют проблему сохранения циклов с использованием блоков себя в целом, но ваш Q был:

Так почему не просто strongSelf = self?

Ответ на этот Q:

Если бы это сделать, self будет частью закрытия блока и всегда сохраняется. Вся история со слабым «я» была бы бессмысленной.

0

Необходимо очистить одно очко, чтобы не использовать слабый/сильный рисунок, чтобы избежать удержания цикла! Независимо от того, используете ли вы сильную ссылку на себя или на слабость, вы не избегаете сохранения цикла. Сохраняемый цикл прерывается ссылочной переменной! Когда он достигнет конца области, ссылочная переменная отменяется. Слабая/сильная структура - это всего лишь механизм защиты, который мешает вам сделать ссылку на nil, так как до того, как блок будет создан и запущен, сам может быть освобожден.

Смежные вопросы