2011-01-07 52 views
2

我一直在嘗試首次使用目標C塊,因爲我非常喜歡在諸如Python和Haskell等語言中使用閉包。從目標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]; 
} 

這不過既然你複製並在方法調用釋放位HAP-危險,但是這是你需要怎麼做,在這種特殊情況下。

+1

從文檔: - (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay「此方法保留接收器和anArgument參數,直到執行選擇器爲止。所以,該解決方案還應該在複製後自動釋放該塊。 – 2011-04-08 18:39:57