2

Я пытаюсь использовать объективные c-блоки в первый раз, потому что мне действительно понравилось использование закрытий на таких языках, как Python и Haskell.Выполнение селектора из блока Objective C

У меня возникла проблема, однако я надеюсь, что кто-то сможет помочь.

Ниже представлена ​​простейшая версия проблемы, которую я испытываю.

typedef void(^BlockType)(NSString *string); 

- (void)testWithtarget:(id)target action:(SEL)action 
{ 
    BlockType block = ^(NSString *string) { 
     [target performSelector:action withObject:data]; 
    }; 

    block(@"Test String"); // Succeeds 

    [self performSelector:@selector(doBlock:) withObject:block afterDelay:5.0f]; 
} 

- (void)doBlock:(BlockType)block 
{ 
    block(@"Test String 2"); // Causes EXC_BAD_ACCESS crash 
} 

Так что, кажется, какой-то вопрос управления памятью, которая не удивит меня, но я просто не хватает знаний, чтобы увидеть решение. Возможно, то, что я пытаюсь, возможно даже невозможно.

интересно посмотреть, что другие люди думают :)

ответ

5

Блок не сохраняется, так как он присутствует только в стеке. Вам нужно скопировать его, если вы хотите использовать его за пределами текущего стека (т. Е. Потому, что вы используете afterDelay:).

- (void)testWithtarget:(id)target action:(SEL)action 
{ 
    BlockType block = ^(NSString *string) { 
     [target performSelector:action withObject:data]; 
    }; 

    block(@"Test String"); // Succeeds 

    [self performSelector:@selector(doBlock:) withObject:[block copy] afterDelay:5.0f]; 
} 

- (void)doBlock:(BlockType)block 
{ 
    block(@"Test String 2"); 
    [block release]; 
} 

Это немного хап-опасности, однако, так как вы копируете и отпускание через вызовы методов, но это, как вы должны были бы сделать это в данном конкретном случае.

+1

Из документации: - (void) performSelector: (SEL) aSelector withObject: (id) anArgument afterDelay: (NSTimeInterval) delay "Этот метод сохраняет приемник и параметр anArgument до тех пор, пока селектор не будет выполнен". Таким образом, решение должно также автоповторить блок после копии. –