2011-04-15 68 views
2

我有一个导航控制器提供的UIViewController。此的UIViewController异步加载的图像,如下所示:图像异步加载 - 如果处理崩溃

[self performSelectorInBackground:@selector(downloadData) withObject:nil]; 
- (void)downloadData { 

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

    LocationDetails * details = [[LondonDatabase database] locationDetails : UniqueID]; 

    NSData * imageData = [NSData dataWithContentsOfURL : [NSURL URLWithString : [details image]]]; 
    picture = [[UIImage alloc ]initWithData:imageData]; 

    [self performSelectorOnMainThread : @selector(updateUI) withObject : nil waitUntilDone : NO]; 

    [pool release]; 

} 

的问题是,如果这个视图控制器被弹出而上述方法与错误执行应用程序崩溃的堆栈:

布尔_WebTryThreadLock (bool),0x61b3950:尝试从主线程或Web线程以外的线程获取网络锁 。这可能是 是从辅助线程调用UIKit的结果。碰撞 现在...

任何人都可以帮忙吗?

感谢,

马丁

回答

4

使用NSThread,并保持一个句柄,在视图控制器对象。当视图控制器释放时,取消线程(假设它还没有完成)。在downloadData中,在尝试访问视图控制器的元素之前检查线程是否未被取消。也就是说,如果线程已被取消,则返回。我有类似的问题,这就是我解决它的方法。

下面的代码(这是加载图像到定制表格单元格):

 
-(void)displayImage:(id)context 
{  
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    UIImage *image = (UIImage *)context; 

    [spinner stopAnimating]; 
    brandImage.image = image; 
    [brandImage setNeedsDisplay]; 
    [pool release]; 
} 

-(void)fetchImage:(id)context 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    NSString *url = (NSString *)context; 

    if ([[NSThread currentThread] isCancelled]) 
     return; 

    UIImage *image = [ArtCache imageForURL:url]; 
    if (![[NSThread currentThread] isCancelled]) { 
     [self performSelectorOnMainThread:@selector(displayImage:) withObject:image waitUntilDone:NO]; 
    } 

    [pool release]; 
} 

-(void)showBrandImageURL:(NSString *)url 
{ 
    [spinner startAnimating]; 
    brandImage.image = nil; 
    if (imageLoadThread) { 
     [imageLoadThread cancel]; 
     [imageLoadThread release]; 
    } 
    imageLoadThread = [[NSThread alloc] initWithTarget:self selector:@selector(fetchImage:) object:url]; 
    [imageLoadThread setThreadPriority:0.8]; 
    [imageLoadThread start]; 
} 

这些是在定制表格单元格类3种方法。最后一个是从cellForRowAtIndexPath:调用的。另外两个支持被调用的那个。

+0

干杯标记。线程优先级是否应该是0.8? – GuybrushThreepwood 2011-04-15 19:31:24

+0

@Ohnomycoco:不,你可以忽略线程优先级指令。我们使用的表格单元非常复杂,需要很长时间来准备。我们将图片加载到后台任务中,如果它有所不同,我们降低线程的优先级以加快UI的其他部分(以及表格加载)。让这个行动成为一个主线是一个巨大的胜利。改变线程优先级的好处并不明显。 :-) – 2011-04-15 19:33:59