Как правильно избежать Retain Cycle при использовании блоков

Каков правильный способ добавления объектов в NSMutableArray, который строго определяется свойством.

[tapBlockView setTapBlock:^(UIImage* image) {
   [self.myImageArray addObject:image]; // self retain cycle
}

Если я создам слабую ссылку что-то вроде

__weak NSMutableArray *array = self.myImageArray;
[tapBlockView setTapBlock:^(UIImage* image) {
    [array addObject:image]; // If I will do this then how will I update original Array ?
}

я тоже пробовал

__weak id weakSelf = self;
[tapBlockView setTapBlock:^(UIImage* image) {
    [weakSelf storeImageInaNewMethod:image]; // Calling SToreImageInaNewMethod
}

и

-(void)storeImageInaNewMethod:(UIImage*)image {
   [self.myImageArray addObject:image]; // This again retaining cycle
}

Каков правильный способ обновления исходного объекта, определенного свойством?


person Tariq    schedule 06.11.2012    source источник
comment
Блоки подобны указателям на функции. Разве вы не можете просто установить блок в nil, когда он вам больше не нужен?   -  person Ramy Al Zuhouri    schedule 06.11.2012


Ответы (4)


Попробуйте комбинацию 2-го и 3-го.

__weak id weakSelf = self;
[tapBlockView setTapBlock:^(UIImage* image) {
    [weakSelf.myImageArray addObject:image];
}
person rmaddy    schedule 06.11.2012
comment
Обратите внимание, что это действительно только в том случае, если вы используете weakSelf в первой строке блока, если вы сначала делаете что-то еще, вам нужен ответ Каана. - person malhal; 24.07.2016

После ответа Мэдди - это из лекции WWDC 2012 года по GCD и асинхронному программированию:

__weak MyClass *weakSelf = self;

[tapBlockView setTapBlock:^(UIImage* image) {
    __strong MyClass *strongSelf = weakSelf;
    if(strongSelf) {
        [strongSelf.myImageArray addObject:image];
    }
}];
person Kaan Dedeoglu    schedule 06.11.2012
comment
Я не понимаю, почему ты снова меняешься на __strong? Я думаю, достаточно только этого кода? [weakSelf.myImageArray addObject: изображение]; - person Tariq; 06.11.2012
comment
Причина приведения обратно к __strong состоит в том, чтобы гарантировать, что если weakSelf все еще жив, когда выполняется первая строка блока, он будет продолжать жить до конца выполнения блока. - person Carl Veazey; 25.02.2013
comment
Если бы вы включили предупреждения, то поняли бы, зачем нужен __strong: слабая переменная может исчезнуть в любой момент, в том числе в середине вызова weakSelf.myImageArray, что наверняка вызовет проблемы. - person gnasher729; 28.04.2015

В вашем случае вам нужно только сослаться на массив, на который ссылается self, поэтому:

NSMutableArray *array = self.myImageArray;
[tapBlockView setTapBlock:^(UIImage* image)
                          {
                             [array addObject:image]; // No cycle
                          }];

Работает нормально, при условии, что self.myImageArray не возвращает разные ссылки на массивы в разное время. Цикла нет: текущий объект ссылается на массив и блок, а блок, в свою очередь, ссылается на массив.

Если self.myImageArray действительно возвращает разные ссылки на массивы в разное время, используйте слабую ссылку на self, ваш случай 3.

person CRD    schedule 06.11.2012

Ваши второй и третий кажутся правильными. Второй работает, потому что вы не создали копию массива, так что он все еще указывает на исходный. Третий работает, потому что ссылка на себя слаба.

person Catfish_Man    schedule 06.11.2012
comment
Второй работает, только если self.myImageArray возвращает прямую ссылку на ivar. Это может быть небезопасным предположением. - person rmaddy; 06.11.2012