![](/img/trans.png)
[英]UITextField clears while scrolling in UITableView - custom cell
[英]UITableView with custom cell scrolling slowly
我有三个不同的单元格。 Cell01,Cell02和Cell03。 Cell01必须只出现一次,在表格视图的顶部,其余的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目录中获取图像需要花费一些时间,每当您滚动到表格视图时,都会创建一个新单元格并从Doc目录中加载图像,这需要一些时间。 尝试在单元格上使用图像的延迟加载。 还要在新线程而不是主线程中加载图像。
苹果有一个示例项目可以帮助您。 延迟加载表视图
希望对您有帮助。
考虑异步加载图像。 您可以将对所有UIImageView
的引用保留在可变数组中,开始在异步块中加载图像,例如使用GCD,然后在加载图像时更新图像视图。
这是一个大概的外观示例(假设您有一个ivar NSMutableArray *_imageViews
,并使用正确的元素大小进行了初始化,并用nil填充)。 我是从臀部开始编码的,但是希望您能理解。 顺便说一句,您可以通过将[NSNull null]
插入可变数组来填充[NSNull null]
。
我保证,如果正确实现此功能,滚动速度将得到显着改善:)
- (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";
[_imageViews replaceObjectAtIndex:row withObject:cell.someImage];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
UIImage *image = [self imageInDocumentsDirectoryWithName:@"thirdimage" andSize:CGSizeMake(200, 200)];
// because UI needs to be updated on the main thread,
// dispatch yet another block.
dispatch_async(dispatch_get_main_queue(), ^{
UIIMageView *imageView = [_imageViews objectAtIndex:row];
ImageView.image = image;
});
});
}
// et cetera
}
我刚刚完成了类似的工作,如果您确保documents目录中的所有图像都已经是正确的尺寸(200 x 200),则可以正常工作而不必异步加载。
如果需要更大的图像,则在保存原始文件时会生成正确大小的缩略图,因为它实际上需要过多的处理才能实时调整图像大小。
但是在这种情况下,您只有三个图像。 如果仅在调整图像大小后缓存图像并继续重复使用(而不是制作新图像),那么它的速度甚至会更快 。
当前的实现存在两个潜在的性能问题。 首先是使用NSBundle
而不是UINib
来加载nib文件。 每次NSBundle
从文件系统重新加载nib文件,而UINib
会一次读取nib文件并将其内容缓存在内存中。 由于不需要每次都从文件系统中重新读取nib,因此使用UINib
实例化对象应该快UINib
数量级。
所以不要这样做...
cell = [[[NSBundle mainBundle] loadNibNamed:@"Cell02" owner:self options:nil] objectAtIndex:0];
...做这个:
cell = [UINib loadNibNamed:@"Cell02" owner:self] objectAtIndex:0];
第二个问题是相似的。 当前的实现是每次都从文件系统中重新加载相同的映像,而不是将它们缓存在内存中并重新使用它们。 为了解决这个问题,您可以添加一个NSArray
或NSDictionary
类型的实例变量(取决于您希望检索图像的方式),然后在加载图像之前进行检查以查看其是否已在集合中。 如果不是,请加载图像并将其存储在集合中,然后再使用。 否则,请使用缓存的图像,而不是再次加载它。
所以不要这样做...
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
而不是NSDictionary
来帮助防止缓存过大。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.