Objective-C — Блоки и управление памятью?

__weak MyClass *selfReference = self;

dispatch_async(dispatch_get_main_queue(), ^{
        [selfReference performSomeAction];
    });
  • Когда вам нужно передать слабую ссылку на блок?
  • Применяется ли это правило к dispatch_async, а также к пользовательским блокам?
  • Блок копирует используемые в нем iVars или сохраняет их?
  • Кому принадлежат переменные, инициализированные внутри блока? Кто должен их освобождать?

person aryaxt    schedule 31.08.2012    source источник
comment
На все эти вопросы есть ответы в документации Apple.   -  person Jonathan Grynspan    schedule 31.08.2012
comment
@JonathanGrynspan Вы могли бы указать на документацию?   -  person mathk    schedule 31.08.2012
comment
@JonathanGrynspan developer.apple.com/library/ios/#documentation/cocoa/Conceptual/ Вот ссылка на документацию, но она не отвечает на мои вопросы   -  person aryaxt    schedule 31.08.2012
comment
@aryaxt: Продолжай читать. Это все есть. :)   -  person Jonathan Grynspan    schedule 31.08.2012
comment
@Jonathan Grynspan Обратите внимание, что в ссылочном документе не упоминается ARC, но некоторые вещи о блоках WRT ARC, например __block, теперь создающие сильную ссылку, изменились.   -  person zaph    schedule 04.05.2013


Ответы (1)


1, 2) Блоки сохраняют в себе указатели на объекты (любые блоки, блоки dispatch_async — ничего особенного). Обычно это не проблема, но может привести к циклам сохранения, поскольку блок может быть связан с объектом-владельцем, и этот объект-владелец (часто self) может сохраняться блоком. В этом случае вы должны использовать слабую переменную, а затем переназначить ее для сильного захвата:

__weak MyClass *weakSelf = self;
self.block = ^{
    MyClass *strongSelf = weakSelf;
    ...
    [strongSelf ...];
    [strongSelf.property ...];
    [strongSelf->iVar ...];
 }

Примечание. Если вы обращаетесь к iVar напрямую, компилятор преобразует его в self->iVar и, таким образом, сохраняет self!

3) Блоки сохраняют только указатели, но не копируют их.

4) Переменные, созданные внутри блока, принадлежат этому блоку и будут освобождены, когда этот блок выйдет за пределы области действия.

person Fabian Kreiser    schedule 31.08.2012
comment
Фабиан, не могли бы вы прокомментировать, почему вам нужно переназначить сильный указатель? - person x89a10; 27.02.2013
comment
Если вы не создадите сильное свойство, 1) компилятор запрещает использование оператора -› и вы не можете получить доступ к iVars и 2) слабая переменная может быть освобождена во время выполнения блока. Чтобы убедиться, что переменная не освобождается во время выполнения блока, вам нужно будет присвоить ее сильной переменной перед ее использованием. - person Fabian Kreiser; 27.02.2013
comment
Вопрос касался dispatch_async, но в ответе об этом не говорится. - person zaph; 06.09.2013