2013-02-07 49 views
4

我在委托方法内创建了一个块,并使用它在另一个类中调用静态方法。即使启用NSZombies,我也会收到EXC_BAD_ACCESS错误。这里对于有关类似问题的几个职位 - 我觉得这一个是最接近:ARC:EXC_BAD_ACCESS在委托方法内从块内调用方法

ARC: Getting EXC_BAD_ACCESS from inside block used in delegate method

但是,我没有发现任何东西至今已帮助。下面是代码:

@interface MyClass() 
@property (nonatomic, copy) CaseBlock c; 
@end 

.... 

//NSURLConnection delegate method 
- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
{   
    NSDictionary *d = [NSDictionary dictionaryWithObjectsAndKeys: 
         //blows up after executing this 
         ^() { [AnotherClass staticMethod]; },authURL, 
         ^() { NSLog(@"TODO");}, searchURL, 
         ^() { NSLog(@"TODO"); }, itemURL, 
         nil]; 
    self.c = [[d objectForKey:[self.url path]] copy]; 

    if (self.c) { 
     self.c(); 
    } else { NSLog(@"WARN unexpected response path"); } 

} 

这是我曾尝试使用块的第一次,但我可以告诉大家,这是造成问题,因为调用外部块正常工作的方法。而且,据我所知,我写的所有代码都会被执行,然后发生EXC_BAD_ACCESS错误。但是,我是Objective-C的新手,所以如果我错了,请纠正我。

+0

我做了一个更简化的示例代码版本,并没有得到崩溃。你说它在实例化字典时崩溃了? –

+0

不完全超熟悉块,但我的猜测是块不是对象(就像一个int),所以你不能把它当作一个对象,因此你不能把它放到字典中。 – TheAmateurProgrammer

+1

@TheAmateurProgrammer块可以视为对象('id')。据我所知,他们只响应一个选择器“副本”。如果从内存堆栈复制它们,可以安全地存储在集合中。 – Tricertops

回答

9

如果需要超出创建的范围,则需要复制块。由于dictionaryWithObjectsAndKeys:处理的是一般对象而不是特定块,因此它不知道复制它们,所以您必须先复制它们,然后再通过它们到它。

NSDictionary *d = [NSDictionary dictionaryWithObjectsAndKeys: 
        //blows up after executing this 
        [^() { [AnotherClass staticMethod]; } copy], authURL, 
        [^() { NSLog(@"TODO");} copy], searchURL, 
        [^() { NSLog(@"TODO"); } copy], itemURL, 
        nil]; 
+0

哦!是的,我认为这是问题,但我也认为这个副本处理它:self.c = [[d objectForKey:[self.url path]] copy];谢谢 - 它现在有效。 – minus

+0

@CarolineM:堆栈块只在声明的范围内有效(在这种情况下,它被用作方法调用的参数,所以它的范围就是该方法调用)。您需要在它无效之前将其复制,并且由于该方法不会为您复制它,所以您必须在将该块传递给方法之前将其复制 – newacct