查看[返回单元格]之前的最后一行..加载图像后,滚动速度正在降低......似乎滚动卡住了
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = @"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:MyIdentifier] autorelease];
}
int storyIndex = [indexPath indexAtPosition: [indexPath length] - 1];
NSString *itemDescription=[[stories objectAtIndex: storyIndex]
objectForKey:@"title"];
CGRect aframe = CGRectMake(80, 30, 250, 40);
textLabel = [[UILabel alloc] initWithFrame:aframe];
textLabel.font = [UIFont boldSystemFontOfSize:14];
textLabel.numberOfLines=0;
textLabel.textColor = [UIColor darkTextColor];
textLabel.backgroundColor = [UIColor whiteColor];
[cell.contentView addSubview:textLabel];
textLabel.text=itemDescription;
CGRect frame = CGRectMake(0, 0, 70,80);
UIImageView *TopImageView = [[UIImageView alloc] init];
[cell.contentView addSubview:TopImageView];
TopImageView.frame=frame;
m_strImage = [m_imglinkArray objectAtIndex:storyIndex];
TopImage = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:m_strImage]]];
TopImageView.image=TopImage;
return cell;
}
你能帮助我提高卷轴的速度吗?
此致
阿伦
答案 0 :(得分:2)
我相信你这里可能有两个问题。首先是没有多线程化图像加载的问题,其次是你如何使用UITableViewCell。
只要屏幕上出现一个单元格,iPhone就会调用cellForRowAtIndexPath - 如果向下滚动,当您再次向上滚动时,上面的所有内容都会被卸载并重新加载。如前所述,这可以通过多线程模式解决 - 链接发布到markj.net,和/或使用NSThread。 NSThread的优势在于您可以更灵活地处理问题或加载不仅仅是图像数据。 (我会同时使用)
为了有效地执行此操作,您需要具有自定义UITableViewCell。无论如何都可以,因为您可以让表格单元格负责其内容而不是视图控制器,并且您可以有效地操作单元格格式和内容。以下是关于UITableCellView的精彩帖子的链接:http://blog.atrexis.com/index.cfm/2009/1/6/iPhone--Customize-the-UITableCellView
当您实现UITableViewCell时,请尽量将所有addSubView和格式化调用放在“if(cell == nil)”块中,仅如果您不能将它们放入自定义initWithFrame中。您会发现iPhone正在堆叠您添加的每个子视图 - 它不会清除旧视图。您可以通过将所有背景颜色设置为“UIColor clearColor”然后在命中之间更改文本来查看此工作 - 您将看到一堆文本在彼此之上。这通常不可见,因为实心背景会覆盖所有“旧”子视图。
在结合这两种方法之前,考虑实施“模型”。你有一个视图和一个控制器,但你的所有数据都应该在一个模型中。所有图像URL,内容等应该类似于NSMutableArray,您自己的自定义对象,或者可能通过SQLite。拥有模型后,您可以实现图像的缓存。通过缓存,所有图像将保留在应用程序的负载之间,这将节省电池,带宽和时间。
我愿意: 1.将所有数据放入某种模型中(NSMutableArray,SQLLite,某些东西) 2.实现自己的自定义UITableViewCell 3.确保在cellForRowAtIndexPath的活动块内有0个addSubView,init或alloc调用 4.使用委托示例或NSThread在后台加载所有图像 5.添加本地图像缓存
关于缓存图像的Apple论坛上有一些很好的例子。
答案 1 :(得分:2)
nessence有很多好消息。还有一些想法:
你在这里疯狂地泄漏。你创建的每个单元都泄漏了2个UILabel,一个UIImageView和一个UIImage。
如前所述,您不仅会泄露这些内容,而且还会在您的视图中累积,因为您使用addSubview将其中一个放在另一个上面。:
在单元格绘制期间到达网络速度非常慢并且阻止了您的UI。如果这些URL是本地的,那么你可以使用UIImage的+ imageWithContentsOfFile,如果没有,你需要在后台加载它。
我认为你不需要这里的线程。 NSURLConnection是一种在后台加载数据的好方法,不会产生线程开销。
nessence完全正确,你需要一个Story的模型类。
可重用单元配置的基本方法不正确。您没有获取可重用的单元格,然后向其添加子视图。应将所有子视图添加到if()块中以创建单元格。然后,在每次传递中,您只需更改事物的值。我已经重写了下面的一些代码来演示。这仍然不是正确的代码,因为它在单元格绘制期间到达网络,并且这可能是在子视图单元(而不是自定义单元格)中的太多元素,但它更接近正确的想法。我甚至不知道这是否汇编;我只是在这里打字。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = @"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
// Here we do all our cell creation
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:MyIdentifier] autorelease];
// Make the label
CGRect aframe = CGRectMake(80, 30, 250, 40);
UILabel *textLabel = [[[UILabel alloc] initWithFrame:aframe] autorelease]; // Note the -autorelease so we don't leak
textLabel.font = [UIFont boldSystemFontOfSize:14];
textLabel.numberOfLines=0;
textLabel.textColor = [UIColor darkTextColor];
textLabel.backgroundColor = [UIColor whiteColor];
textLabel.tag = DescriptionTag; // A tag so we can find it later (you'll need a constant for this)
[cell.contentView addSubview:textLabel];
// And the second label
aframe = CGRectMake(80, 30, 250, 40);
textLabel = [[[UILabel alloc] initWithFrame:aframe] autorelease];
textLabel.font = [UIFont boldSystemFontOfSize:14];
textLabel.numberOfLines=0;
textLabel.textColor = [UIColor darkTextColor];
textLabel.backgroundColor = [UIColor whiteColor];
textLabel.tag = TitleTag;
[cell.contentView addSubview:textLabel];
// The image view
CGRect frame = CGRectMake(0, 0, 70,80);
UIImageView *topImageView = [[[UIImageView alloc] init] autorelease];
topImageView.frame = frame;
topImageView.tag = TopImageTag;
[cell.contentView addSubview:topImageView];
}
// all the above was cell creation; we do that as seldom as possible.
// Now we do cell configuration. We want this to be fast.
UILabel *descriptionLabel = (UILabel*)[cell.contentView viewWithTag:DescriptionTag];
descriptionLabel.text = itemDescription;
UILabel *titleLabel = (UILabel*)[cell.contentView viewWithTag:TitleTag];
titleLabel.text =[[stories objectAtIndex:indexPath.row] objectForKey:@"title"];
NSString *imageURLString = [m_imglinkArray objectAtIndex:storyIndex]; // You should have a model class called Story, not two arrays.
UIImage *image = [[[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:imageURLString]]] autorelease]; // This is still way too slow if it's a remote URL
UIImageView *imageView = (UIImageView*)[cell.contentView viewWithTag:TopImageTag];
imageView.image = image;
return cell;
}
我建议您花一些时间学习TableViewSuite,Practical Memory Management和Coding Guidelines for Cocoa。一段时间研究Cocoa的基础知识也很有用,因为这里的编码风格表明你可能没有坚实的基础。虽然这是一本Mac书,但我仍然推荐Cocoa Programming for Mac OS X。如果您有兴趣使用它来学习iPhone,我会整理一个可能有帮助的syllabus。我还没有审查过,但斯坦福大学的在线CS193P course看起来很有希望。
答案 2 :(得分:1)
这里已多次询问过,您需要做的是为每个单元格加载异步图像,以防止滚动速度变慢。
这称为“懒图像加载”,我在这里引用苹果教程: Lazy load images in UITableView
答案 3 :(得分:0)
每次表视图要求获取行的单元格时,似乎都是从URL加载。这发生在主应用程序线程(用户界面线程)中,它会阻止用户界面,使其无法响应。
特别是如果此网址是您从互联网加载的资源,则此暂停很大。
我建议您应该在后台线程中加载图像并显示占位符图像,直到从网络中提取它们。
您可以尝试以下网址中提供的解决方案......