【问题标题】:A faster way to update interface using background threads使用后台线程更新界面的更快方法
【发布时间】:2013-05-11 11:21:40
【问题描述】:

我正在构建一个光谱仪,想知道如何提高基于UIView 的代码的性能。我知道我无法从后台线程更新 iPhone/iPad 的用户界面,所以我使用 GCD 进行大部分处理。我遇到的问题是我的界面更新太慢了。

使用下面的代码,我尝试使用 32 个堆叠的 4x4 像素 UIViews 并更改它们的背景颜色(请参阅所附图像上的绿色方块)。该操作会为其他用户界面产生明显的滞后。

有没有办法我可以从某种后台线程“准备”这些颜色,然后要求主线程一次刷新界面?

//create a color intensity map used to color pixels
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    colorMap = [[NSMutableDictionary alloc] initWithCapacity:128];

    for(int i = 0; i<128; i ++)
    {
        [colorMap setObject:[UIColor colorWithHue:0.2 saturation:1 brightness:i/128.0 alpha:1] forKey:[NSNumber numberWithInt:i]];
    }


});

-(void)updateLayoutFromMainThread:(id)sender
{
    for(UIView* tempView in self.markerViews)
    {
        tempView.backgroundColor =[colorMap objectForKey:[NSNumber numberWithInt:arc4random()%128]];
    }

}
//called from background, would do heavy processing and fourier transforms
-(void)updateLayout
{

    //update the interface from the main thread
    [self performSelectorOnMainThread:@selector(updateLayoutFromMainThread:) withObject:nil waitUntilDone:NO];


}

我最终预先计算了一个包含 256 种颜色的字典,然后根据圆圈试图显示的值向字典询问颜色。试图动态分配颜色是瓶颈。

【问题讨论】:

  • 所以你对你的应用进行了基准测试,结果证明这是瓶颈,对吧?
  • 您表示您的视图是堆叠的。你的意思是只有其中一个是可见的吗?如果是,则解决方案可能是推迟对不可见视图的所有操作,除了下一个(或者如果您的用户可以通过各个视图快速切换,则为接下来的几个)。 WWDC 2012 上有一段视频介绍了如何构建并发用户界面。
  • 几乎我有 256 列,每列有 32 个 UIViews(4px x 4px)。通过堆叠,我的意思是它们以 4 个像素为增量占据 128 个像素。每 200 毫秒左右我想做快速傅立叶变换并使用这些视图对结果频率进行颜色编码(只需更改它们的背景颜色)。
  • 这听起来像你试图模拟一个有很多视图的情节......为什么不只有一个视图,而一个视图真正绘制一个真实的情节......你可以看看 coreplot
  • 您使用的视图过多。 UIView 不是轻量级对象,管理屏幕上的许多视图会降低性能。正如其他评论者所建议的那样,至少对每个条的子组件使用核心图形或使用图层而不是视图来研究绘图。

标签: ios performance cocoa-touch graphics uiview


【解决方案1】:

,是的,有几点。

虽然您不应该在主线程上处理 UIView,但您可以在使用它们之前在后台线程上实例化视图。不确定这是否会对您有所帮助。然而,除了在后台线程上实例化视图之外,UIView 实际上只是 CALayer 对象的元数据包装器,并且针对灵活性而非性能进行了优化。

最好的办法是在后台线程上绘制图层对象或图像对象(这是一个较慢的过程,因为绘制使用 CPU 和 GPU),将图层对象或图像传递给主线程,然后将预渲染的图像绘制到视图层(速度更快,因为只需调用图形处理器即可将图像直接传送到 UIView 的后备存储)。

看到这个答案:

Render to bitmap then blit to screen

代码:

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextDrawImage(context, rect, image);
}

执行速度远快于以相同方法执行其他绘图操作,例如绘制贝塞尔曲线。

【讨论】:

  • 不要认为这有帮助..他正在接近整个事情错误的 IMO
  • 用管理 CAlayer 的视图控制器替换取消视图确实显着提高了性能,因为我可以在后台进行所有处理,然后用预先计算的颜色填充一堆或矩形
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-08
  • 2012-04-24
  • 2013-11-23
  • 1970-01-01
  • 1970-01-01
  • 2016-08-10
相关资源
最近更新 更多