ARC, ivars в блоках и эталонные циклы через Captured Self - PullRequest
26 голосов
/ 04 ноября 2011

Я работаю в чистой среде iOS5 / ARC, поэтому при необходимости могу использовать __слабые ссылки. Во многих ситуациях я делаю ссылки на ivars в блоке, в частности, на блоки анимации, которые перемещают представления, которые являются свойствами, скажем, моего класса контроллера представления.

Мой вопрос:

При самом простом использовании ivars в блоке я создаю контрольный цикл? Нужно ли мне использовать технику __weak self / strong self каждый раз Я пишу блок, который манипулирует переменными экземпляра содержащего объекта?

Я пересматривал сессию WWDC 2011 года № 322 («Достижения Objective-C в глубине»), чтобы понять нюансы, касающиеся 3-минутного сегмента, начиная с индекса времени 25:03 о «Цикле отсчета через захваченное Я». Для меня это означает, что любое использование ivars в блоке должно быть защищено с помощью настройки слабого self / strong self, как описано в этом сегменте.

Пример метода ниже на контроллере представления типичен для анимации, которую я делаю.

В блоке openIris неправильно ли ссылаться на ивары «_topView» и «_bottomView», как у меня?

Должен ли я всегда устанавливать __слабую ссылку на себя перед блоком, затем сильную ссылку в блоке на слабую ссылку, заданную ранее, а затем обращаться к иварам через эту сильную ссылку в моем блоке?

Начиная с сессии WWDC, я понимаю, что ссылка на ivars в блоке действительно создает ссылку на подразумеваемое «я», от которого зависают эти ivars.

Для меня это означает, что на самом деле не существует ни одного простого или тривиального случая, когда правильно получить доступ к иварам в блоке без слабого / сильного танца, чтобы гарантировать отсутствие циклов. Или я читаю слишком много в угловом деле, которое не относится к простым случаям, таким как мой пример?

- (void)openIrisAnimated:(BOOL)animated
{
    if (_isIrisOpened) {
        NSLog(@"Asked to open an already open iris.");
        return; // Bail
    }

    // Put the common work into a block.
    // Note: “_topView” and “_bottomView” are the backing ivars of 
    // properties “topView” and “bottomView”
    void (^openIris)() = ^{
        _topView.frame     = CGRectMake(....);        
        _bottomView.frame  = CGRectMake(....);
    };

    // Now do the actual opening of the iris, whether animated or not:
    if (animated) {
        [UIView animateWithDuration:0.70f 
                         animations:^{
                             openIris();
                         }];
    }
    else {
        openIris();
    }

    _irisOpened = YES; // Because we have now just opened it
}

Вот как я переписал бы часть блока openIris, используя руководство из Сессии # 322, но мне просто интересно, требуется ли для всех моих подобных блоков этот слабый / сильный эталонный танец для обеспечения правильности и стабильности:

__weak MyClass *weakSelf = self;


void (^openIris)() = ^{
     MyClass *strongSelf = weakSelf;

     if (strongSelf) {        
        strongSelf.topView.frame     = CGRectMake(....);
        strongSelf.bottomView.frame  = CGRectMake(....);
     }
};

Действительно ли это необходимо?

Ответы [ 2 ]

22 голосов
/ 04 ноября 2011

Здесь есть только цикл, если self затем продолжает хранить ссылку на блок (или что-то, принадлежащее self). Если нет, то вы можете идти, так как время жизни блока не продиктовано тем, что он сохранил.

Так что в вашем конкретном примере вы, кажется, в чистом виде. Анимационные блоки не должны участвовать в танце слабого / сильного себя.

4 голосов
/ 24 ноября 2011

Случай, о котором стоит беспокоиться, похож на addObserverForName:object:queue:usingBlock:.Документы говорят: «Блок копируется центром уведомлений».В ARC это слово «копия» является красным флагом;теперь вам нужно предпринять шаги, чтобы вы (абонент) не протекали.

РЕДАКТИРОВАТЬ: Кроме того, иногда сама ARC будет предупреждать вас.Блок завершения -[UIPageViewController setViewControllers:direction:animated:completion:] является показательным примером.Я бы никогда не заподозрил, что использование self может привести к циклу сохранения, но ARC предупредил, что это произойдет, поэтому я на всякий случай исполнил слабый-сильный танец.

...