2009-11-08 190 views
5

我有一种情况,我懒加载从www的图像。
这是一个项目列表,当一个项目被点击时,一个详细视图被推送到导航控制器。Cocoa-Touch:performSelectorOnMainThread:奇怪的行为+崩溃

在该详细信息视图中,该项目具有图像,首先是默认图像,我想从网址开始加载图像。

所以我要做的就是创造出初始化一次分离一个新的线程这反过来加载内容和事后通知我认为该数据被加载的对象:

// in MyLoader: 
- (MyLoader *)initWithUrl:(NSURL *)url requester:(id)requester { 
    self.url = url; 
    self.requester = requester; // both are nonatomic, retain properties 
    [self performSelectorInBackground:@selector(loadIt) withObject:nil]; 
} 

- (void)loadIt { 
    NSAutoreleasePool *arp = [[NSAutoreleasePool alloc] init]; 
    NSData *data = [NSData dataWithContentsOfURL:url]; 
    [requester performSelectorOnMainThread:@selector(dataReady) withObject:data waitUntilDone:YES; 
    [arp release]; 
} 

// in MyRequester: 
- (void)somewhere { 
    MyLoader *loader = [[[MyLoader] alloc] initWithUrl:someUrl requester:self] autorelease]; 
    // then I retain loader somewhere, it's more complicated but I have verified that it's properly retained. 
} 

的几个注意事项:

  1. 首先我认为可能有一些变量的问题。我在performSelectorOnMainThread之前设置了一个断点,并确认datarequester都正常。

  2. 然后,我认为这是由NSData跨线程引起的,所以我改变了withObject:nil。它仍然崩溃。

  3. 当我进一步调查时,撞车事件很奇怪。我指定waitUntilDone:YES,我在requesterdataReady中放置了一个断点。但performSelectorOnMainThread调用返回(它到达它后面的断点),但未达到dataReady内的断点。顺便说一句,- (void)dataReady:(NSData*)的身体现在只包含int x = 1;(放置一个断点)。另外,我试过设置waitUntilDone:NO,它仍然崩溃。

  4. 未执行选择器(未达到断点),但在调用后不久发生崩溃。

有没有人知道有什么问题?

这是显而易见的,但只是要清楚,如果我只是注释掉[requester performSelectorOnMainThread...部分,它不会崩溃。

此外,这是一个堆栈跟踪,但它根本没有帮助。

#0 0x00a71004 in ___TERMINATING_DUE_TO_UNCAUGHT_EXCEPTION___() 
#1 0x93436e3b in objc_exception_throw() 
#2 0x0028aca6 in __NSThreadPerformPerform() 
#3 0x00a098e1 in CFRunLoopRunSpecific() 
#4 0x00a08c48 in CFRunLoopRunInMode() 
#5 0x0005a78d in GSEventRunModal() 
#6 0x0005a852 in GSEventRun() 
#7 0x0168a003 in UIApplicationMain() 
#8 0x000028d4 in main (argc=1, argv=0xbffff100) at /Users/myName/Document/appName/main.m:14 
+1

我怀疑有更简单的方法来查看未捕获的异常,但尝试包装int retVal = UIApplicationMain(argc,argv,nil,nil);在您的main.m文件中使用try/catch块并检查或打印出异常。可能会提供一些线索。我知道我可以在这样的事情之后继续点击(在调试器中),并最终打印原因。但这可能是由于我的.gdbinit文件中的一些设置。我的。gdbinit有NSException的一些断点... – wkw 2009-11-09 00:07:22

回答

9

您有:

[requester performSelectorOnMainThread:@selector(dataReady) withObject:data waitUntilDone:YES; 

应该是:

[requester performSelectorOnMainThread:@selector(dataReady:) withObject:data waitUntilDone:YES; 

通知:@selector(dataReady :)(结肠癌) 既然你传递一个参数该方法假定数据就绪定义如下:

- (void) dataReady:(NSData *)theData ... 
+1

缺少冒号,而不是分号。冒号是方法名称的一部分。 – NSResponder 2009-11-09 04:27:50

+11

未来,您可以通过转到您的构建设置并在其他警告标志中添加-Wundeclared-selector来捕获此信息。这将导致在上述情况下引发警告,其中选择器不匹配任何已知的方法。 – 2009-11-09 18:37:45