Iphone Cocoa Touch:performselectornmainthread:weird behavior+;崩溃

Iphone Cocoa Touch:performselectornmainthread:weird behavior+;崩溃,iphone,objective-c,cocoa-touch,Iphone,Objective C,Cocoa Touch,我有一种情况,我懒得从www加载图像。 这是一个项目列表,当点击一个项目时,一个细节视图被推送到导航控制器 在这个细节视图中,项目有一个图像,首先是一个默认图像,我想开始从URL加载它的图像 因此,我要做的是创建一个对象,该对象一旦初始化就会分离一个新线程,该线程依次加载内容,然后通知我的视图数据已加载: // in MyLoader: - (MyLoader *)initWithUrl:(NSURL *)url requester:(id)requester { self.url =

我有一种情况,我懒得从www加载图像。
这是一个项目列表,当点击一个项目时,一个细节视图被推送到导航控制器

在这个细节视图中,项目有一个图像,首先是一个默认图像,我想开始从URL加载它的图像

因此,我要做的是创建一个对象,该对象一旦初始化就会分离一个新线程,该线程依次加载内容,然后通知我的视图数据已加载:

// 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.
}
请注意:

  • 首先,我认为一些变量可能有问题。我在
    performSelectorOnMainThread
    前面放了一个断点,并确认
    data
    requester
    都正常

  • 然后我认为这是由于跨线程传递NSData造成的,所以我更改了
    with object:nil
    。它仍然崩溃

  • 当我进一步调查时,这起车祸非常奇怪。我指定了
    waitUntilDone:YES
    ,我在
    请求者的
    dataReady
    中放置了一个断点。但是
    performSelectorOnMainThread
    调用返回(它到达断点之后),而没有到达
    dataReady
    中的断点。顺便说一句,
    -(void)dataReady:(NSData*)
    的正文现在只包含
    intx=1(用于在上放置断点)。另外,我尝试设置
    waitUntilDone:NO
    ,它仍然崩溃

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

  • 有人知道怎么了吗

    这是显而易见的,但需要明确的是,如果我只是注释掉
    [requester performselectornmainthread…
    部分,它不会崩溃

    另外,这里有一个堆栈跟踪,但它一点用处都没有

    #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
    
    你有:

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

    [requester performSelectorOnMainThread:@selector(dataReady:) withObject:data waitUntilDone:YES;
    
    注意:@selector(dataReady:)(带冒号) 由于将参数传递给该方法,因此假定该方法的数据就绪定义如下:

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

    我怀疑有更简单的方法可以查看未捕获的异常,但请尝试使用try/catch块在主.m文件中包装int-retVal=UIApplicationMain(argc,argv,nil,nil);并检查或打印出异常。可能会提供一些线索。我知道,在类似这样的情况下(在调试器中),我可以点击continue它最终会打印出原因。但这可能是由于my.gdbinit文件中的某些设置。my.gdbinit有一些NSException的断点…缺少冒号,而不是分号。冒号是方法名称的一部分。将来,您可以通过转到生成设置并在其他警告标志中添加-Wundeclared选择器来捕获此问题。This将导致在上述情况下抛出警告,其中选择器与任何已知方法都不匹配。