Должен ли я скопировать блок здесь? - PullRequest
6 голосов
/ 14 января 2012

Я понимаю, что вы должны копировать блоки, чтобы они оставались после выхода из стекового фрейма. Но как это применимо к выделенным в стеке блокам, используемым во вложенном блоке, как в следующем примере кода:

- doSomethingFunkyThenCall:(void(^)(int someValue))callback
{
    [[NSOperationQueue currentQueue] addOperationWithBlock:^{
        // ... do some work here, potentially nesting into further blocks ...
        callback(result);
    }];
}

Очевидно, что кадр стека doSomethingFunkyThenCall: завершится до выполнения обратного вызова, поэтому его придется скопировать. Но произойдет ли это автоматически при вызове на addOperationWithBlock: или мне придется делать это вручную?

Ответы [ 2 ]

3 голосов
/ 14 января 2012

Скорее всего, это произойдет автоматически.Принципы проектирования Какао в целом подразумевают, что вы не несете ответственности за объекты (их управление памятью, проходящие блоки (которые фактически реализованы как надлежащие объекты Objective-C] и т. Д.), Которые вы не создали.Таким образом, вы можете просто передать полученный блок в качестве параметра, и среда выполнения будет управлять им в соответствии с его потребностями.

0 голосов
/ 14 января 2012

Да, вы должны сделать callback = [[callback copy] autorelease]; в начале этого метода.

Объекты, используемые в блоках, сохраняются автоматически, но отправка сохранения блока стека фактически ничего не делает (потому что семантика сохранения требует, чтобы он возвращал получателя), поэтому исчезнет, ​​как только мы покинем кадр, в котором он был создан.

Источники:
http://cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html http://thirdcog.eu/pwcblocks/#objcblocks

РЕДАКТИРОВАТЬ: Оказывается, я не прав. Ниже @bbum указывает, что Block_copy будет копировать рекурсивно, а поскольку addOperationWithBlock: копирует свой блок, обратный вызов также копируется.

...