代码之家  ›  专栏  ›  技术社区  ›  samvermette

滚动性能和ui图像绘制

  •  4
  • samvermette  · 技术社区  · 14 年前

    我正在构建一个类似于iPod的UITableView。应用程序的相册浏览视图:

    我将在首次发布时从iPod库中导入所有艺术家和专辑作品。将所有内容保存到coredata并将其返回到nsfetchedresultscontroller。我正在重用单元标识符,并且在我的 cellForRowatindexPath: method i have this code:。

    artist*artist=[提取结果控制器对象索引路径:索引路径];
    nsstring*identifier=@“BigCell”;
    
    swartistView单元格*单元格=(swartistView单元格*)[表视图DequeueRusableCellWithIdentifier:标识符];
    
    如果(单元格=零)
    cell=[[[swartistviewcell alloc]initWithStyle:uiTableViewCellStyleDefault ReuseIdentifier:identifier]autorelease];
    
    cell.artist name=艺术家.艺术家名称;
    cell.artWorkImage=[uiImageImageWithData:artist.image];
    
    [单元格集需要显示];
    
    返回细胞;
    < /代码> 
    
    

    我的swartistviewcell实现了drawrect:method to draw both the string and image:。

    [artworkmage drawinrect:cgrectmake(0,1,44,44)]
    [艺名drawtoint:cgpointmake(54,13)for width:200 with font:[uifont-boldSystemFontOfSize:20]linebreakMode:uilinebreakModeClip];
    < /代码> 
    
    

    滚动仍然是曲折的,我只是不明白为什么。像ipod和twitter这样的应用程序有着平滑的滚动效果,但它们都像我一样在手机中绘制了一些小图像。

    我所有的观点都是不透明的。我错过了什么?

    edit:这是Shark说的:

    我不熟悉鲨鱼。这些符号与什么有关?当我看到这些痕迹时,它们都指向我的drawrect:方法,特别是uiimage绘图。
    BR/>

    如果扼流圈是文件读取,它会指向其他什么吗?这肯定是图纸吗?

    编辑:保留图像

    我已经按照pothibo的建议做了,并向我的artworkmage类添加了一个artworkmage方法,它保留了用imagewithdata创建的图像:

    —(uiimage*)artworkmagemage{
    如果(artworkmage==nil)
    artWorkImage=[[uiimage imagewithdata:self.image]retain];
    
    返回ArtWorkImage;
    }
    < /代码> 
    
    

    现在我可以直接将保留的图像设置为TableViewCell,如下所示:

    cell.artworkmage=artist.artworkmage;
    < /代码> 
    
    

    我还将setNeedsDisplay设置在TableViewCell类的setArtWorkImage:方法中。滚动仍然是滞后的,Shark显示的结果完全相同。

    IMG_2316.PNG

    我将在首次发布时从iPod库中导入所有艺术家和专辑作品。将所有内容保存到coredata并将其返回到nsfetchedresultscontroller。我正在重用单元标识符cellForRowAtIndexPath:方法我有这个代码:

    Artist *artist = [fetchedResultsController objectAtIndexPath:indexPath];
    NSString *identifier = @"bigCell";
    
    SWArtistViewCell *cell = (SWArtistViewCell*)[tableView dequeueReusableCellWithIdentifier:identifier];
    
    if (cell == nil)
        cell = [[[SWArtistViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier] autorelease];
    
    cell.artistName = artist.artist_name;
    cell.artworkImage = [UIImage imageWithData:artist.image];
    
    [cell setNeedsDisplay];
    
    return cell;
    

    我的swartistviewscell单元实现了drawRect:绘制字符串和图像的方法:

    [artworkImage drawInRect:CGRectMake(0,1,44,44)]
    [artistName drawAtPoint:CGPointMake(54, 13) forWidth:200 withFont:[UIFont boldSystemFontOfSize:20] lineBreakMode:UILineBreakModeClip];
    

    滚动仍然是曲折的,我只是不明白为什么。像ipod和twitter这样的应用程序有着平滑的滚动效果,但它们都像我一样在手机中绘制了一些小图像。

    我所有的观点都是不透明的。我错过了什么?

    编辑:鲨鱼说:

    alt text

    我不熟悉鲨鱼。这些符号与什么有关?当我看到这些痕迹时,它们都指向我的drawrect:方法,特别是uiimage绘图。

    alt text

    如果扼流圈是文件读取,它会指向其他什么吗?这肯定是图纸吗?

    编辑:保留图像

    我已经按照pothibo的建议做了,并向我的artworkmage类添加了一个artworkmage方法,它保留了用imagewithdata创建的图像:

    - (UIImage*)artworkImage {
        if(artworkImage == nil)
            artworkImage = [[UIImage imageWithData:self.image] retain];
    
        return artworkImage;
    }
    

    现在我可以直接将保留的图像设置为TableViewCell,如下所示:

    cell.artworkImage = artist.artworkImage;
    

    我还将setNeedsDisplay设置在TableViewCell类的setArtWorkImage:方法中。滚动仍然滞后,Shark显示的结果完全相同。

    5 回复  |  直到 13 年前
        1
  •  1
  •   Kris Markel    14 年前

    此时,您最好的选择是使用Shark来尝试在代码中找到瓶颈。苹果有一个“ Performance Tuning Your Application with Shark “(iTunes链接)如果你以前从未使用过鲨鱼,它会带你穿过鲨鱼。不过,我认为你必须是99美元iPhone开发者计划的一员才能看到它。

        2
  •  6
  •   Jonas Byström    14 年前

    您的分析数据强烈地表明瓶颈在于您的PNG图像的解包。我猜58.5%的CPU时间都花在了解包PNG数据上(例如,如果加载中也包含memcpy调用)。可能更多的时间花在了那里,但是没有更多的数据很难说。我的建议是:

    1. 如前所述,将加载的图像保存在uiimage中,而不是nsdata中。这样,您就不必每次显示图像时都进行png解包。
    2. 将您的图像加载到工作线程中,以不影响主线程的响应(同样多)。创造一个工人真的很容易:

      [自我执行selectornmainthread:@selector(preloadThreadEntry:)withObject:nil waitUntildone:no];

    3. 预先加载图像,比如100行或更多行(比如70行在滚动方向,30行在相反方向)。如果你所有的图像都需要88x88像素的视网膜,100个图像需要不超过2 MB。

    4. 当您对名为“png”、“gz”、“inflat”等的内容进行更多的分析时,这些调用可能不会在您的列表中下降,但它们肯定不会以如此糟糕的方式影响应用程序的感觉。

    只有当你在这之后仍然有性能问题时,我建议你研究一下缩放,例如,为视网膜加载“.'.'.'.'.@2x.png”图像。祝你好运!

        3
  •  4
  •   Pier-Olivier Thibault    14 年前

    [uiimage imagewithdata:]不缓存。

    这意味着每次传入该数据源方法时,Coregraphic都会解压缩并处理您的图像。

    我会将您的艺术家对象更改为保留uiimage而不是nsdata。如果你经常收到的话,你可以在记忆学习中刷新图像。

    另外,我不建议在数据源调用中使用setNeedsDisplay,我将在您的单元中使用它。

    setNeedsDisplay不是对drawRect的直接调用:

    它只告诉操作系统在运行循环结束时再次绘制uiview。可以在同一个runloop中调用setNeedsDisplay 100次,操作系统只调用一次drawRect方法。

        4
  •  1
  •   Noah Witherspoon    14 年前

    如果延误发生在 -drawRect ,那么你可能想看看 this article :tweetie的开发人员非常详细地解释了他使用的方法来实现你想要的平滑滚动。不过,从那时起,这变得更容易了: CALayer 有一个 shouldRasterize 基本上将其子层展平为位图的属性,然后只要层内没有任何变化,该属性就可以使层周围的动画效果更好,例如 UITableView 当你滚动它的时候。在这种情况下,您可能会将该属性应用于您的个人 UITableViewCell S层。

        5
  •  1
  •   Nick Forge    14 年前

    我的猜测是延迟来自于在核心数据中存储图像。核心数据通常不是存储大量数据块的好方法。

    更好的解决方案是将图像存储为磁盘上的单个文件,使用相册ID标识每个图像。然后,您将设置一个内存缓存,将图像存储在RAM中,以便快速加载到 UIImageView s.理想情况下,需要在后台线程(例如,尝试performselectoronbackgroundthread)上加载从磁盘到RAM的图像,这样I/O就不会阻塞主线程(这将影响您的滚动性能)。

    附录1

    如果你只是打电话 -drawRect: 每个单元加载一次(正如您应该这样),那么问题可能是图像的缩放。通过在代码中绘制图像,使用 drawInRect 将使用CPU时间,因此另一种方法是在从iPod库接收图像时对其进行缩放(如果需要多个尺寸的图像,请按需要的每个尺寸保存一个版本)。导入数据时,可能需要在后台线程上执行此操作,以避免阻塞主(UI)线程。

    另一个需要考虑的问题是 UIIVIEVIEW 可能是使用核心动画进行缩放,这意味着它是硬件加速的(我不确定事实是否如此,我只是猜测)。切换到 UIIVIEVIEW 因为图像将因此摆脱了CPU对图像缩放的负担。合成开销会略有增加,但这可能是接近“最佳”滚动性能的最简单方法。