Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/101.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 自定义单元格缓慢滚动的UITableView_Iphone_Ios_Objective C_Tableview_Custom Cell - Fatal编程技术网

Iphone 自定义单元格缓慢滚动的UITableView

Iphone 自定义单元格缓慢滚动的UITableView,iphone,ios,objective-c,tableview,custom-cell,Iphone,Ios,Objective C,Tableview,Custom Cell,我有三个不同的细胞。Cell01、Cell02和Cell03。Cell01只能在tableview的顶部出现一次,其余的02和03必须插值(02,03,02,03(…) 问题是滚动TableView时存在一些“滞后”。我正在从文档文件夹加载图像,我也在调整它的大小,以不需要太多的处理,但它仍然滚动缓慢。它正在重用单元格(我检查了if(!cell)) 这是我的密码: - (UITableViewCell *)tableView:(UITableView *)tableView cellForRow

我有三个不同的细胞。Cell01、Cell02和Cell03。Cell01只能在tableview的顶部出现一次,其余的02和03必须插值(02,03,02,03(…)

问题是滚动TableView时存在一些“滞后”。我正在从文档文件夹加载图像,我也在调整它的大小,以不需要太多的处理,但它仍然滚动缓慢。它正在重用单元格(我检查了
if(!cell)

这是我的密码:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{    
    int row = indexPath.row;

    if (row == 0) {
        Cell01 *cell = nil;
        cell = [tableView dequeueReusableCellWithIdentifier:@"Cell01ID"];
        if (!cell) {
            cell = (Cell01*)[[[NSBundle mainBundle] loadNibNamed:@"Cell01" owner:self options:nil] objectAtIndex:0];
            cell.someLabel.text = @"First";
            cell.someImage.image = [self imageInDocumentsDirectoryWithName:@"mainimage" andSize:CGSizeMake(200, 200)];
        }

    } else if (row % 2 == 0) {
        Cell02 *cell = nil;
        cell = [tableView dequeueReusableCellWithIdentifier:@"Cell02ID"];
        if (!cell) {
            cell = (Cell02 *)[[[NSBundle mainBundle] loadNibNamed:@"Cell02" owner:self options:nil] objectAtIndex:0];
            cell.randomLabel.text = @"Second";
            cell.someImage.image = [self imageInDocumentsDirectoryWithName:@"secondimage" andSize:CGSizeMake(200, 200)];
        }
    } else {
        Cell03 *cell = nil;
        cell = [tableView dequeueReusableCellWithIdentifier:@"Cell03ID"];
        if (!cell) {
            cell = (Cell03 *)[[[NSBundle mainBundle] loadNibNamed:@"Cell03" owner:self options:nil] objectAtIndex:0];
            cell.anotherLabel.text = @"Third";
            cell.someImage.image = [self imageInDocumentsDirectoryWithName:@"thirdimage" andSize:CGSizeMake(200, 200)];

        }
    }
}


- (UIImage *)imageInDocumentsDirectoryWithName:(NSString *)fileName andSize:(CGSize)size
{    
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString* path = [documentsDirectory stringByAppendingPathComponent:fileName];
    UIImage *image = [UIImage imageWithContentsOfFile:path];
    image = [image resizedImageToFitInSize:size scaleIfSmaller:YES];

    return image;
}

你知道如何改进这个tableview(并使它滚动得更快)吗?

我认为滚动得慢是因为从文档目录将图像加载到单元格中。从Doc dir获取图像需要一些时间,当您滚动表视图时,将创建一个新单元格,并从Doc dir加载图像,这需要一些时间。尝试在单元格上延迟加载图像。还将图像加载到新线程而不是主线程中

有一个苹果的示例项目可以帮助我们


我希望这将有助于您。

考虑异步加载图像。您可以将对所有
UIImageView
的引用保留在可变数组中,开始在异步块中加载图像,例如使用GCD,然后在加载图像视图时更新图像视图

下面是一个粗略的示例,展示了它的外观(假设您有一个ivar
NSMutableArray*\u imageViews
,用正确大小的元素初始化,并用nils填充)。我是从这里开始编代码的,但我希望你能明白我的意思。顺便说一句,您可以通过在可变数组中插入
[NSNull]
来用nils填充该数组

我保证,如果您正确地实现了这一点,您将看到滚动速度的显著提高:)


我刚刚完成了类似的实现,如果您确保documents目录中的所有图像都已经是正确的大小(200x200),那么它就可以正常工作,而无需异步加载

如果需要将图像放大,则在保存原始文件时生成大小正确的缩略图,因为要“实时”调整图像大小,实际上需要进行大量处理


但在本例中,您只有三个图像如果您只是在图像调整大小后缓存图像并继续重复使用它(而不是创建新图像),那么它的速度将更快。

当前实现存在两个潜在的性能问题。第一种方法是使用
NSBundle
而不是
UINib
加载nib文件
NSBundle
每次都从文件系统重新加载nib文件,而
UINib
只读取一次nib文件并将其内容缓存在内存中。由于它不需要每次都从文件系统中重新读取nib,因此使用
UINib
实例化对象应该快几个数量级

所以与其这样做

cell = [[[NSBundle mainBundle] loadNibNamed:@"Cell02" owner:self options:nil] objectAtIndex:0];
cell.someImage.image = [self imageInDocumentsDirectoryWithName:@"thirdimage" andSize:CGSizeMake(200, 200)];
…这样做:

cell = [UINib loadNibNamed:@"Cell02" owner:self] objectAtIndex:0];
第二个问题是类似的;当前的实现是每次从文件系统重新加载相同的映像,而不是将它们缓存在内存中并重用它们。要解决此问题,您可以添加类型为
NSArray
NSDictionary
的实例变量(取决于检索图像的方式),然后在加载图像之前检查图像是否已在集合中。如果没有,请加载图像并在使用前将其存储在集合中。否则,将使用缓存的图像,而不是再次加载它

所以与其这样做

cell = [[[NSBundle mainBundle] loadNibNamed:@"Cell02" owner:self options:nil] objectAtIndex:0];
cell.someImage.image = [self imageInDocumentsDirectoryWithName:@"thirdimage" andSize:CGSizeMake(200, 200)];
…这样做:

// Note: Consider defining constants for the keys/filenames.

UIImage *image = [self.cachedImages objectForKey:@"thirdimage"];
if (image == nil) {
    image = [self imageInDocumentsDirectoryWithName:@"thirdimage" andSize:CGSizeMake(200, 200)];
    [self.cachedImages setObject:image forKey:@"thirdimage"];
}

cell.someImage.image = image;

如果需要缓存大量的图像,请考虑使用<代码> nSCache > /COD>而不是<代码> NSCORCHOR> <代码>,以防止缓存过大。