Какъв е правилният начин да избегнете 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
}

Какъв е правилният начин за актуализиране на оригиналния обект, дефиниран от property?


person Tariq    schedule 06.11.2012    source източник
comment
Блоковете са като указатели на функции. Не можете ли просто да зададете блока на нула, когато вече не ви трябва?   -  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 на първия ред на блока, ако първо направите нещо друго, тогава имате нужда от отговора на Kaan. - 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
Не разбирам защо отново се променяш на __силен? Предполагам, че само този код е достатъчен? [weakSelf.myImageArray addObject:image]; - 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