В чем разница между слабой и блочной ссылкой?


я читаю документацию Xcode, и вот что меня озадачивает:

__block typeof(self) tmpSelf = self;
[self methodThatTakesABlock:^ {
    [tmpSelf doSomething];
}];

из документации копируется следующее:

блок формирует сильную ссылку на переменные, которые он захватывает. Если вы используете self внутри блока, блок формирует сильную ссылку к self, Так что если self также имеет сильную ссылку на блоке (который обычно делает), сильные результаты цикла ссылки. Чтобы избежать цикла, вам нужно к создайте слабого (или __block) ссылка на себя вне блока, как в приведенном выше примере.

Я не понимаю, что значит слабая (или )'?

и

__block typeof(self) tmpSelf = self;

и

__weak typeof(self) tmpSelf = self;

точно так же здесь?

я нашел еще один кусок в документе:

Примечание: В среде сбора мусора, если вы применяете оба __weak и __block модификаторы к переменной, затем блок не будет гарантировать, что он остался жив.

Итак, я совершенно озадачен.

3 70

3 ответа:

из документов о _ _ block

__блочные переменные живут в хранилище, которое совместно используется между лексической областью переменной и всеми блоками и копиями блоков, объявленными или созданными в лексической области переменной. Таким образом, хранилище переживет разрушение кадра стека, если какие-либо копии блоков, объявленных в кадре, выживут за пределами конца кадра (например, будучи помещенными в очередь где-то для последующего выполнения). Несколько блоков в данном лексическая область может одновременно использовать общую переменную.

из документов о _ _ weak

__weak указывает ссылку, которая не поддерживает жизнь объекта ссылки. Слабая ссылка имеет значение nil, когда нет сильных ссылок на объект.

Так что технически это разные вещи. __block-это остановить копирование переменной из внешней области в область блока. __weak-это самоограничение слабых указатель.

обратите внимание, что я сказал технически, потому что для вашего случая они будут делать (почти) то же самое. Единственное различие заключается в том, используете ли вы ARC или нет. Если ваш проект использует ARC и предназначен только для iOS4.3 и выше, используйте __weak. Он гарантирует, что ссылка установлена в ноль, если глобальная ссылка на область каким-то образом освобождается. Если ваш проект не использует ARC или предназначен для более старых версий ОС, используйте __block.

здесь есть тонкая разница, убедитесь, что вы понимаете оно.

редактировать: еще один кусочек головоломки-это __небезопасных_ - носителя. Этот модификатор почти такой же, как __слабый, но для среды выполнения до 4.3. Однако он не установлен на ноль и может оставить вас с висячими указателями.

в режиме ручной подсчет ссылок, __идентификатор блока х; имеет эффект не сохраняя х. В режиме дуги, __идентификатор блока х; значения по умолчанию для сохранения х (как и все остальные значения). Чтобы получить ручное поведение режима подсчета ссылок в ARC, вы можете использовать __unsafe_unretained __block id x;. Однако, как следует из названия __unsafe_unretained, наличие нераспределенной переменной опасно (потому что она может болтаться) и поэтому не рекомендуется. Два лучших варианта-либо использовать _ _ weak (если вы не нужно поддерживать iOS 4 или OS X v10.6) или установить значение __block равным нулю, чтобы прервать цикл сохранения.

apple docs

помимо других ответов на _ _ block vs __weak, есть еще один способ избежать сохранения цикла в вашем сценарии.

@weakify(self);
[self methodThatTakesABlock:^ {
    @strongify(self);
    [self doSomething];
}];

подробнее о @Weakify @Strongify Marco