__block цикл самоопределения в блоке ivar в ARC - PullRequest
9 голосов
/ 18 января 2012

У меня есть некоторый код с очевидным циклом ссылок в блоке ivar.Следующий код вызывает цикл ссылки, и dealloc никогда не вызывается:

__block MyViewController *blockSelf = self;

loggedInCallback = ^(BOOL success, NSError *error){
    if (success)
    {
        double delayInSeconds = 1.0;
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void)
        {
            [blockSelf.delegate loginDidFinish];
        });            
    }
};

Однако, если я создаю другую переменную __block, которая будет содержать ссылку на мой делегат для захвата области действия блока, цикл ссылки будетпрочь:

__block id <MyViewControllerDelegate> blockDelegate = self.delegate;

loggedInCallback = ^(BOOL success, NSError *error){
    if (success)
    {
        double delayInSeconds = 1.0;
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void)
        {
            [blockDelegate loginDidFinish];
        });            
    }
};

Просто хочу понять, что здесь происходит.

1 Ответ

16 голосов
/ 18 января 2012

Я предполагаю, что вы используете ARC здесь. До ARC ваш первый пример работал бы просто отлично. С ARC семантика __block изменилась. __block декларации теперь сильно захвачены, а не слабо. Замените __block на __weak в первом примере, и все должно работать как положено.

Что касается работы второго примера, вы создаете сильную ссылку на делегат, но у вас нет ссылки на ваш объект. Таким образом, нет цикла, и все счастливы.

Я рекомендую прочитать статью Майка Эша об изменениях, внесенных в ARC, особенно в отношении захвата блоков и __weak http://www.mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference-counting.html

...