Копирование блоков (т.е. копирование их в переменные экземпляра) в Objective-C - PullRequest
19 голосов
/ 17 апреля 2010

Я пытаюсь понять блоки. Я получаю, как использовать их как обычно, когда передается непосредственно в метод. Теперь мне интересно взять блок, сохранить его (скажем) в переменной экземпляра и вызвать его позже.

Руководство по программированию блоков звучит так, как будто я могу это сделать, используя Block_copy / retain, чтобы скопировать блок, но когда я пытаюсь запустить его, у меня вылетает программа.

- (void) setupStoredBlock
{
    int salt = 42;
    m_storedBlock = ^(int incoming){ return 2 + incoming + salt; };
    [m_storedBlock retain];
}

Я пытаюсь позвонить позже:

- (void) runStoredBlock
{
    int outputValue = m_storedBlock(5);
    NSLog(@"When we ran our stored blockwe got back: %d", outputValue);
    [m_storedBlock release];
}

У кого-нибудь есть идеи? (Или есть что-то, что я не получаю с блоками?)

Большое спасибо!

Ответы [ 4 ]

30 голосов
/ 17 апреля 2010

Вместо этого вы захотите сделать это:

- (void) setupStoredBlock
{
    int salt = 42;
    m_storedBlock = Block_copy(^(int incoming){ return 2 + incoming + salt; });
}
6 голосов
/ 21 января 2013

• Как и все локальные переменные, в стеке существует нестатический блок, который извлекается из стека, как и любая другая локальная переменная, которая не была объявлена ​​статической.

• Block_copy () копирует блок из стека в кучу, где существуют все экземпляры malloc. И, как и все методы new / copy, Block_copy () возвращает выделенный объект кучи с счетом сохранения 1. Блок - это объектjectiveC, но он не соответствует, как обычный объект. Следовательно, не должно быть никакой разницы между Block_Release () и методом объективного выпуска.

• В этом примере используется метод копирования экземпляра блока. Потому что присвоение результата Block_copy () идентификатору требует приведения типа, который я не хочу ошибаться. Метод копирования позволяет назначать переменную блока непосредственно идентификатору.

 - (void) setupStoredBlock
{
    int zStackLocalVariable = 42;
    iHeapAllocatedVariable = [^int(int aMore){ return zStackLocalVariable + aMore; } copy];
}

• Объявление статического объекта означает, что он должен быть физически выделен вместе с самим кодом. Блок, который объявлен как статический, запрещает компилятору доступ к переменным вне его собственной области видимости. Из-за требований объявления статического блока я предполагаю, что блок в стеке несколько отличается от блока в куче.

• Блок - это объект-объект c, чей класс, имя класса и другую связанную информацию которого я еще не пытался получить, но, подобно протоколу, объекту и другим скрытым классам targetC, он не соответствует NSObject. Однако, как и все объекты targetC, он должен соответствовать для сохранения / освобождения. ARC расширяет функции сохранения и освобождения также и для базовых объектов Foundation, и, возможно, если не сейчас, то, в конечном итоге, в распределениях malloc / free.

• Я жду истинную мотивацию для тщательного изучения mikeash.com , поскольку яблоко любит держать нас всех на каком-то гипертеоретическом плане небольшого физического значения, хотя все, что важно, это физическое .

ARC и блоки также обсуждаются здесь

6 голосов
/ 21 апреля 2010

Скопируйте блок, когда вы хотите, чтобы он оставался рядом. Выпустите или отпустите, когда закончите. Сохраните его, если вам нужен длинный путь для заклинания /* NOP */.

@interface Foo : FooSuper {}
@property(copy) int (^storedBlock)(int);
@end

@implementation Foo
@synthesize storedBlock = mStoredBlock;

- (void)setupStoredBlock {
    self.storedBlock = ^{/*...*/};
    // or: mStoredBlock = [^{/*...*/} copy];
    // but this simple implementation violates the atomicity contract
}

- (void)runStoredBlock {
    int result = self.storedBlock(5);
    NSLog(@"%s: result = %d", __func__, result);
}
@end
4 голосов
/ 02 ноября 2010

Была очень хорошая презентация на эту тему на недавнем WWDC (2010). В нем описано, как были реализованы блоки и почему вам нужно использовать Block_copy. Вы можете скачать фильм из презентации по адресу: http://developer.apple.com/itunes/?destination=adc.apple.com.4092414566 Фильм называется: «Усовершенствованный Objective-C и сборщик мусора»

...