14

解决方案:使用SDWebImage:https ://github.com/rs/SDWebImage

我有一个 UITableView 在滚动时变得非常滞后。我发现当我使用的图像重新出现在屏幕上时会出现延迟。

我正在使用自定义 UITableViewCell。这也是它落后的原因吗?

我的自定义 UITableViewCell:

在此处输入图像描述

我的代码:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

NSString *CellIdentifier = [NSString stringWithFormat:@"Cell%d%d",indexPath.row,indexPath.section];


tableViewCellActiviteiten *cell = (tableViewCellActiviteiten *)[self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (cell == nil)
{

    NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"tableViewCellActiviteiten" owner:self options:nil];
    cell = (tableViewCellActiviteiten *)[nib objectAtIndex:0];
}


cell.thetitle.text = [self.alletitels objectAtIndex:indexPath.row];
cell.thesubtitle.text = [self.allesubtitels objectAtIndex:indexPath.row];

NSString * imagePath = [self.alleimages objectAtIndex:indexPath.row];

NSURL * imageURL = [NSURL URLWithString:imagePath];
NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage * image = [UIImage imageWithData:imageData];

cell.image.image = image;

return cell;

}

数组内容:

self.alletitels包含一个字符串:“活动标题”

self.allesubtitels包含一个字符串:“活动字幕”

self.alleimages包含一个网址:“ http://m2.myhappygames.com//files/pics/0/Paranormal_Shark_Activity_3.jpg

任何人都可以建议延迟滚动的原因可能是什么?

4

7 回答 7

9

问题是每次tableView: cellForRowAtIndexPath:调用方法时,您的代码都会生成图像。每次屏幕上出现一个单元格时都会调用此方法,因此如果您滚动非常快,此方法将开始同步分配大量图像,这将减慢滚动速度。

作为一种快速的解决方案,在您的视图控制器中实现 NSCache 并将图像存储在其中。

UIImage *image = [_imageCache objectForKey:@indexPath.row];
if (image == nil) {
    NSString * imagePath = [self.alleimages objectAtIndex:indexPath.row];
    NSURL * imageURL = [NSURL URLWithString:imagePath];
    NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
    image = [UIImage imageWithData:imageData];
    [_imageCache setObject:image forKey:@indexPath.row];
}

cell.image.image = image;

_imageCahce 是您可以实现的视图控制器的实例变量。

希望这会有所帮助,干杯!

于 2013-09-18T13:02:24.647 回答
6

这两行在这里:

NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage * image = [UIImage imageWithData:imageData];

是什么显着降低了您的表性能。

每次刷新该单元格时,您都在同步获取和加载图像数据。

以某种方式缓存(或在本地保存)要显示的图像会更聪明。如果它们没有保存在本地或缓存中,那么只有去获取这些图像(并在该“ cellForRowAtIndexPath:”方法之外异步执行该操作)。

于 2013-09-18T12:55:58.527 回答
4

在创建单元时,您正在进行同步网络调用以下载图像。这些调用会阻塞主线程,直到用于单元下载的图像。延迟时间会因网络质量而异。

解决方案是使用称为“延迟加载”的技术。在这种技术中,图像加载将在单独的线程上进行,从而解除对主线程的阻塞。图像被下载,然后应用到正确的容器UIImageView。这是Apple 在表格视图中延迟加载图像的示例代码

您也可以使用SDWebImage。这也将为您进行图像缓存。

#import <SDWebImage/UIImageView+WebCache.h>

...

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *MyIdentifier = @"MyIdentifier";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];

    if (cell == nil)
    {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                       reuseIdentifier:MyIdentifier] autorelease];
    }

    // Here we use the new provided setImageWithURL: method to load the web image
    [cell.imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
                   placeholderImage:[UIImage imageNamed:@"placeholder.png"]];

    return cell;
}

希望有帮助!

于 2013-09-18T13:07:49.653 回答
3

除了缓存,您还可以考虑使用 Grand Central 调度在后台加载图像。加载单元格时,放置一个 UIActivityIndi​​cator 然后将其替换为单独线程中的图像。

// get a data provider referencing the relevant file
CGDataProviderRef dataProvider = CGDataProviderCreateWithFilename(filename);

// use the data provider to get a CGImage; release the data provider
CGImageRef image = CGImageCreateWithPNGDataProvider(dataProvider, NULL, NO, 
                                                kCGRenderingIntentDefault);
CGDataProviderRelease(dataProvider);

// make a bitmap context of a suitable size to draw to, forcing decode
size_t width = CGImageGetWidth(image);
size_t height = CGImageGetHeight(image);
unsigned char *imageBuffer = (unsigned char *)malloc(width*height*4);

CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();

CGContextRef imageContext =
CGBitmapContextCreate(imageBuffer, width, height, 8, width*4, colourSpace,
              kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little);

CGColorSpaceRelease(colourSpace);

// draw the image to the context, release it
CGContextDrawImage(imageContext, CGRectMake(0, 0, width, height), image);
CGImageRelease(image);

// now get an image ref from the context
CGImageRef outputImage = CGBitmapContextCreateImage(imageContext);

// post that off to the main thread, where you might do something like
// [UIImage imageWithCGImage:outputImage]
[self performSelectorOnMainThread:@selector(haveThisImage:) 
     withObject:[NSValue valueWithPointer:outputImage] waitUntilDone:YES];

// clean up
CGImageRelease(outputImage);
CGContextRelease(imageContext);
free(imageBuffer);

你也可以使用 UIImage+ImmediateLoad.m 它立即解码图像。除了 UIImage -initWithContentsOfFile:, -imageWithCGImage: 和 CG* 在 iOS4 之后是线程安全的。

于 2013-09-24T18:12:00.937 回答
2

您正在尝试在滚动的同一 UI 线程上加载图像。您应该将它们加载到后台缓存,然后在它们准备好显示时从缓存中获取。

于 2013-09-18T12:57:11.790 回答
2

您正在为每个图像进行同步网络调用,这就是您在应用程序中遇到延迟的原因。尝试AsyncImageView 它将从网络异步下载您的图像。而且您将能够从您的应用程序中消除滞后。:-)

于 2013-09-24T14:03:24.563 回答
2

我遇到了类似的问题,我用 Profiler 对其进行了检查,所以这里有一些问题:

1)您使用了错误的可重用标识符,您应该始终使用相同的标识符。

而不是这个:

NSString *CellIdentifier = [NSString stringWithFormat:@"Cell%d%d",indexPath.row,indexPath.section];

用这个:

NSString *CellIdentifier = @"MyIdentifier";

更多阅读:如何使用 UItableViewCell 重用标识符

2) loadNibNamed 方法真的很慢(加上你每次都为每个单元格加载它),你应该摆脱 nib,并通过覆盖 UITableViewCell 的这个方法来放置代码中的 UI 元素

-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier;

3) 使用仪器

于 2013-09-23T13:55:37.407 回答