iPhone SDK后台线程图片加载问题

时间:2010-05-31 11:34:07

标签: iphone objective-c uiimage

我创建了一个显示内容的六个“单元格”的网格视图。在每个单元格中,从Web加载图像。此网格有多个页面(用户通过向上/向下滑动来查看下一组单元格。)

每个单元格都有自己的视图控制器。当这些视图控制器加载时,它们使用我加载的ImageLoader类并显示图像。这些视图控制器实现了一个ImageLoaderDelegate,它具有一个在图像加载完成后调用的方法。

ImageLoader在后台线程上工作,然后在加载完成后通知其委托,将图像传递给委托方法。

麻烦的是,如果用户在图像加载完成之前移动到网格内容的下一页(释放使用ImageLoaders的GridCellViewControllers),则应用程序崩溃。我怀疑这是因为沿着这条线,异步方法完成并尝试通知其委托但不能因为它已被释放。

这里有一些代码可以提供更好的图片:

GridCellViewController.m:

- (void)viewDidLoad {
    [super viewDidLoad];

    // ImageLoader  
    _loader = [[ProductImageLoader alloc] init];
    _loader.delegate = self;

    if(_boundObject)
        [_loader loadImageForProduct:_boundObject]; 
}

//ImageLoaderDelegate method
- (void) imageDidFinishLoading: (UIImage *)image {
    [_imgController setImage:image];
}

ProductImageLoader.m

- (void) loadImageForProduct: (Product *) product {
    // Get image  on another thread
    [NSThread detachNewThreadSelector:@selector(getImageForProductInBackground:) toTarget:self withObject:product];
}

- (void) getImageForProductInBackground: (Product *) product {
    NSAutoreleasePool *tempPool = [[NSAutoreleasePool alloc] init];

    HttpRequestLoader *tempLoader = [[HttpRequestLoader alloc] init];

    NSURL *tempUrl = [product getImageUrl];

    NSData *imageData = tempUrl ? [tempLoader loadSynchronousDataFromAddress:[tempUrl absoluteString]] : nil;

    UIImage *image = [[UIImage alloc] initWithData:imageData];

    [tempPool release];

    if(delegate)
        [delegate imageDidFinishLoading:image];
}

该应用与EXC_BAD_ACCESS崩溃。

免责声明:代码略有修改,专注于手头的问题。

1 个答案:

答案 0 :(得分:1)

有一半时间我在这里问一个问题,不久后我想出了一个解决方案。写下问题可能是解决方案的90%。

无论如何,这就是我所做的,并且可能会有所改进,因为我仍然怀疑这些线程。

事实证明问题是委托方法仍然会触发(imageDidFinishLoading),但委托已经被释放。通过在GridCellViewController.m中释放时将委托显式设置为nil,消息永远不会触发。

GridCellViewController.m

- (void) dealloc {
    if(_loader) {
        _loader.delegate = nil;
        [_loader release];
    }
}