什么是可接受的FPS滚动,以及提高性能的提示是什么?

我在许多WWDCvideo中看到,要尽可能接近60.0 FPS以获得更好的平滑滚动体验。 我有一个UIScrolLView一次加载图像和几个表视图。 目前我得到30 FPS。 这是推荐的FPS的一半。 只是想知道什么FPS你们通常得到一个表视图/滚动视图加载图像和其他重要的东西/渲染的东西。

任何其他提示opsiming FPS? 我已经花了上个星期,直到现在使用时间分析器,分配和核心animation工具来启动乐器,尽可能地进行优化。

只是为了澄清一下我有什么。 我在iPad上有砖石/瀑布/ pinterest风格的布局。 所以这不仅仅是一个普通的UITableView。 这是一个UIScrollView填充整个屏幕,并充满了一些UIView的。 每个视图都有一个150×150的UIImageView和一个UITableView,同时它也有一些用Core Text绘制的标签。 所以,当你看到屏幕时,一眼就可以看到5-8个表格视图,每个单元格都有一个UIImageView,然后每个单元格渲染使用核心文本绘制的归属标签。

所以你可以想象这有多深和复杂。 这不仅仅是一个带有UIImageView的常规表格视图。 我知道如何获得60 FPS只有一个UITableView与UIImage的iPhone。 这个概念是asynchronous加载图像,而不是尽可能地阻塞主线程。

编辑:

看来这里的问题是我在我的视图中的UITableView ..当我从UIView中删除,我得到真正平滑的滚动..

我上传了一个简单版本的示例项目,但它清楚地显示了这个问题。 链接在这里

许多事情影响渲染性能,这里有一些项目,你可以检查:

  • 个人资料 – 你说你已经做了这么好的工作! 不幸的是,简介往往被忽视,即使它可以揭示意想不到的问题。 在一个应用程序中,我正在用不同的单元格表示date的日历。 起初,细胞之间的滚动变慢,这是意想不到的。 我想也许是画了太多的细胞。 分析后,我发现[NSCalender currentCalender]正在使用我CPU时间的85%! 修好之后,一切都滚动很好!

  • 图像 – 大图像在CoreGraphics中投入了大量的负担。 滚动特别需要大量的绘制操作来移动它们。 一个技巧是尽可能less地缩放设备上的图像,这使得CoreGraphics的工作变得更容易。 如果图像是显示图像的两倍,则在显示视图之前调整UIImage的大小。 iOS设备最好处理PNG。 它们在编译时被工具(pngcrush)压缩,iOS有专门的硬件来渲染它们。

  • 自定义绘图 – 如果可能的话,减less自定义CGContext绘图的数量。 很多自定义绘图对animation速度有负面影响。 如果可能的话,我会考虑在复杂的自定义绘图上使用图像。

  • 剔除 – 只绘制你需要的东西。 UITableView自动卸载并加载单元格,因此这是为您完成的,但任何自定义CGContext绘图都应该只在该部分可见时才能完成。 另外自动查看阴影在我的经验中可能会很慢。

  • 重用 – 在UITableView上使用重用标识符,这将允许UITableView重用单元对象,而不是在滚动时重新分配 – 请看这个问题的答案。 也重用UIImages而不是分配多个相同的文件。 imageNamed自动caching图像,但文件的imageFromContents没有。

  • 创build你自己的 – 你可以创build自己的网格视图类,将其隐藏在屏幕外的子视图视图中,并用惰性内容加载滚动。 通过编写定制解决scheme,您可以完全控制stream程并创build针对使用情况优化的devise。 对于大多数使用情况,您将难以构build比Apple标准更好的东西,但我已经在特定情况下看到了这一点。

  • 最后的手段 – 缩小违规视图的尺寸(改善滤液),将内容分成多个页面,缩小图像尺寸,剪掉效果不佳的旧设备。 在牺牲大部分的东西之前,我会select30 FPS。 设备将继续变得更快,旧设备将被淘汰,并且您的应用将逐渐变快。

我用我的UITableViewController接近60 fps,其中表格包含大约2000个单元格,每个单元格从networking中拉出一个图像。 诀窍是懒惰加载图像,因为你需要他们。 这个来自Apple的示例代码非常有帮助。

总体思路是通过不阻塞主线程来保持UI的响应。 在另一个线程上执行下载和其他耗时的任务。

我会做一些名为Lazy Loading,它不会加载图像,直到他们真正看到。

下面是一个很好的例子: http : //www.cocoacontrols.com/platforms/ios/controls/mhlazytableimages

祝你好运!

我所做的是使用NSCache。 我创build了一个符合NSCache数据协议(它真的很容易)的属性的小类。 所以我所做的就是在主表中的每个单元格和值得高速caching的各种单元之间创build一个关系:NSAttributedstring,图像等 – 真正需要创build的任何东西。 我不会预装它,但你可以。

当您被要求通过tableview提供一个单元格时,请在您的caching中查找主要对象。 如果有的话,拉出所有你需要的物体。 如果caching没有对象,那么以旧的方式获取数据,但在完成之前,也将其保存在caching中。

这真的帮助我减less滚动单元格时的“口吃”。 另外,不要在单元格中创build任何animation,这会杀死性能。 一切都应该完全呈现。

另一件要记住的事情 – 确保任何可以设置为不透明的视图的属性设置为YES。 肯定有助于系统呈现单元格(如果使用的话,包括背景视图)。

编辑:

所以你提供的信息,包括UITableViews可能是根本问题。 所以有两点build议:

1)你可以退后一步,找出如何使scrollView单个UITableView? 有了表头和页脚,以及部分页眉和页脚,甚至是基本上使单元格成为浮动视图的能力,难道你不知道如何重新构build你有什么?

2)所以你决定不要build议1.然后,做到这一点。 把tableview所用的空间想象成一个容器视图。 每当tableview被编辑时,拍摄它的图像快照并保持这个图像。 只要用户开始滚动,交换tableViews的图像。 当scrollView停止交换UITableView回来。这当然会需要一些微调。 实际上,在滚动过程中,您可能会在表格上覆盖不透明的图像快照(这会隐藏它并阻止它被要求绘制自己)。

一般来说,您可以做几件事来获得更好的表格视图性能:

1)切换到Loren Brichter绘制UITableViewCell的方法(缺less更好的链接: http : //www.therefinedgeek.com.au/index.php/2010/12/21/fast-scrolling-uitableview-updates-for- ios-4-2 / )

基本上,他所有的代码都是将所有的单元格内容渲染为一个不透明的UIView,UITableView(和CoreGraphics)可以很快地将其展现到UITableViewCell

如果你不想在drawRect中完成所有的单元devise,你仍然可以使用nib,但是:

  • 确保每个子视图都被标记为不透明
  • 没有任何透明/半透明的子视图
  • 没有任何图像的alpha通道!= 1.0f。

2)不要让UIImageView做任何缩放来显示你的图像,给它一个正确大小的UIImage

3)如果您使用的是iOS 5或更高版本,则可以为特定的单元标识符注册一个笔尖。 这样,当你调用[tableView dequeueReusableCellWithIdentifier:],你保证得到一个单元格。 单元分配速度更快(根据苹果),你可以写更less的代码:

 - (void)viewDidLoad { UINib *nib = [UINib nibWithNibName:@"MyCell" bundle:nil]; [self.tableView registerNib:nib forCellReuseIdentifier:@"MyCellIdentifier"]; } // ... - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *cellIdentifier = @"MyCellIdentifier"; MyCell *cell = (MyCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier]; // Commented out code is no longer needed //if (cell == nil) { // cell = [[MyCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; //} // setup cell return cell; } 

4)显示从网上下载的图像

  • 显示默认图像(真实图像下载时要看的东西)
  • 在单独的线程上启动下载(提示:使用GCD的dispatch_async())
  • 当图像进入时,将其caching(提示:NSCache),并将其显示在单元格上
    • 做所有图像下载/cachingclosures主线程; 你应该在主线程上做的唯一事情就是设置图像(记住UI代码已经在主线程上了!)

你可能要编写一个支持asynchronous的UIImageView(或使用现有的库)。

远离EGOImageView,即使它具有asynchronous下载,但在调度到后台线程进行下载之前,它在主线程上执行caching查找(恰好在磁盘上,这意味着昂贵的磁盘IO)。 我曾经使用它,但是我最终编写了自己的一套类来处理这个问题,而且速度更快。

只要按照这些,其他的东西写在这里,你会有桌子的意见,滚动像玻璃在任何时候:)

人眼看到的速度大约是60 FPS,所以这也是推荐的原因,但是30 FPS也会显得非常stream畅,特别是当一个普通用户正在观看它时,而不是你试图尽可能多的修复。 这显然取决于滚动速度有多快,如果帧与帧之间的差异是几个像素的移动,30 FPS将会很好,但更快的移动将需要更高的FPS出现平滑

你要60fps,但实际上30fps看起来不太可怕。 但是我会尽量达到60fps,滚动时更平滑一些。

有许多性能改进的可能性,这也是由各种教程显示

虽然60 FPS是理想的,但像“光晕”这样的游戏在30 FPS下运行得非常漂亮。 “晕”中的战场混乱可能涉及比大多数列表更令人惊讶,快速的动作,甚至像你的复杂动作!