用于UITableViewCell的线程中的图像缓存

时间:2011-09-09 22:57:33

标签: iphone objective-c ios xcode

我有一个图像缓存类,它将配置文件图像存储在NSMutableDictionary中。如果密钥存在,则缓存返回UIImage对象,如果不存在,则下载它,将其存储在字典中,然后返回UIImage。这个共享缓存在NSThreaded方法中调用,如下所示:

[NSThread detachNewThreadSelector:@selector(setImageForUser:) toTarget:self withObject:imageUrlString];

-(void)setImageForUser:(NSString *)imageUrlString {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    LPImageCacher *imageCache = [LPImageCacher sharedCache];
    UIImage *profileImg = [imageCache getCachedImageFromMemory:imageUrlString];
    self.userProfileImageView.image = profileImg;
    if (profileImg == nil) {
        imageUrlString = [[myGlobals sharedInstance].avatarUrlDefault stringByAppendingString:@"/avatar.png"];
        self.userProfileImageView.image = [imageCache getCachedImageFromMemory:imageUrlString];
    }

    [pool release];
}

问题在于,如果他们在加载任何内容之前滚动UITableView,图像会被积压,然后最终加载所有图像,它们会闪烁并更改当前单元格,直到找到正确的图像。我认为在每个单元格中创建一个NSThread实例并且只是取消-prepareForReuse中的线程会很好,但我似乎无法再次重用NSThread对象,关于如何解决这个问题的任何想法?

3 个答案:

答案 0 :(得分:1)

我认为您所看到的问题是由于UIScrollView在您滚动时“冻结”了所有内容。这是一个运行循环问题。为了解决这个问题,您需要确保在默认的运行循环中发送-setImageForUser:消息。

检查这些资源以获取更多信息:

NSURLRequest won't fire while UIScrollView is scrolling

UIScrollView pauses NSTimer until scrolling finishes

希望这有帮助!

答案 1 :(得分:0)

里德奥尔森给了你直接答案。我想提一下。

为每个单元调度线程相当昂贵,为什么不使用NSOperationQueue?您可以让一组工作线程执行每个单独的加载,并且在任何时候将此队列的功能限制为最大可见单元格数是有意义的。这几乎是“重用线程”。

事实上,我建议使用ASIHTTP的ASINetworkQueue。它比NSOperationQueue更简单。

此外,尝试添加简单的优化以在滚动速度低于某个数字时加载单元格。当你无法停下来看它们时,为什么还要加载图像呢?例如,我为tableView写了类似的东西:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    static float prevOffset = 0.0;
    static float scrollSpeed = 0.0;

    // positive -> downwards
    scrollSpeed = scrollView.contentOffset.y - prevOffset;

    if (scrollSpeed < 2.0)
    {
        [self loadImagesForVisibleCellsInTableView:(UITableView*)scrollView];
    }
    else if (scrollSpeed < 6.0)
    {
        shouldLoadImages = YES;
    }
    else
    {
        shouldLoadImages = NO;
    }

    prevOffset = scrollView.contentOffset.y;
}

当tableView快速移动(shouldLoadImages影响tableView:cellForRowAtIndexPath,告诉他们忽略加载图像时)忽略加载新图像,当它即将停止时,它会强制重新加载可见单元格。 / p>

答案 2 :(得分:0)

您应该使用主线程将屏幕更新为用户。这个Common multithreading mistakes beginners make on iPhone将帮助您确定问题。