关于CALayer 的速度 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iOS 开发实用技术导航
NSHipster 中文版
http://nshipster.cn/
cocos2d 开源 2D 游戏引擎
http://www.cocos2d-iphone.org/
CocoaPods
http://cocoapods.org/
Google Analytics for Mobile 统计解决方案
http://code.google.com/mobile/analytics/
WWDC
https://developer.apple.com/wwdc/
Design Guides and Resources
https://developer.apple.com/design/
Transcripts of WWDC sessions
http://asciiwwdc.com
Cocoa with Love
http://cocoawithlove.com/
Cocoa Dev Central
http://cocoadevcentral.com/
NSHipster
http://nshipster.com/
Style Guides
Google Objective-C Style Guide
NYTimes Objective-C Style Guide
Useful Tools and Services
Charles Web Debugging Proxy
Smore
adow
V2EX    iDev

关于CALayer 的速度

  •  
  •   adow
    adow 2012-05-09 00:02:53 +08:00 10121 次点击
    这是一个创建于 4907 天前的主题,其中的信息可能已经有所发展或是发生改变。
    最近在做的一个项目中,需要在UITableViewCell中的UIImageView中显示头像,他们是32*32的正方形小图片,为了实现圆角的效果,我给这个UIImageView设置了CALayer的几个相关属性:

    self.imgAvator.layer.cornerRadius=3.0;
    self.imgAvator.layer.borderWidth=1.0;
    self.imgAvator.layer.borderColor=[UIColor colorWithRed:0 green:0 blue:0 alpha:0.05].CGColor;
    self.imgAvator.clipsToBounds=YES;

    当然他很好的实现了圆角的效果;

    可是在实际运行中,我发现这个UITableView的滚动速度不是很理想,在排除了其他我感觉可能引起的问题之后,我去掉了这个layer的代码,感觉速度有明显的提升了。

    然后,我没有使用layer来实现圆角,而是在获取UIImage后直接做了处理剪裁出圆角图片,这时速度依然比使用layer的明显要快。

    所以我想问的是,使用CALayer的绘图会影响UI的速度吗,有啥优化的办法没有呢?
    15 条回复    1970-01-01 08:00:00 +08:00
    Sai
        1
    Sai  
       2012-05-09 00:17:17 +08:00   1
    Try layer.shouldRasterize = YES;
    txx
        2
    txx  
       2012-05-09 05:24:56 +08:00   1
    我一直觉得coreanimation的效率非常不错

    lz您不会是cell没写好吧。。
    adow
        3
    adow  
    OP
       2012-05-09 11:06:17 +08:00
    @Sai 我用了layer.shouldResterize=YES,速度好像没有明显的改善啊,所以现在还是直接在UIImage上处理之后比较流畅;
    @txx 我也怀疑cell哪里写的有问题,我检查了一些地方,cell reuse 是正常工作的,table的数据现在是从本地的缓存里加载的,我去掉了头像以外所有的数据显示,没有明显的改善,只有去掉layer的几句代码才让我突然感受到流畅不少了,所以我才怀疑这个问题。
    dongsheng
        4
    dongsheng  
       2012-05-09 11:13:41 +08:00   1
    有没有试试直接把图片直接画到cell的CALayer上?额外用UIImageView肯定要消耗更多资源。
    adow
        5
    adow  
    OP
       2012-05-09 11:15:09 +08:00
    google 了一下CALayer,看到了 @livid 的这个http://picky.olivida.com/calayer-and-ipad-apps-performance

    > 每一个 UIView 对象实例都包含一个 CALayer 实例,可以通过 [myView layer] 的方式访问到。而 CALayer 又提供了非常多的邪恶功能,比如修改一个 view 的圆角程度,甚至给它加阴影。这些方法都非常好用。但是代价就是程序的 framerate 就会大受影响,尤其是执行诸如 presentModalViewController 这样全屏幕豪华操作时。

    结论是:要用 CALayer 可以,但是在写到屏幕上之前一定要先将这个 layer 的内容变成一坨简单的 bitmap,否则就等着看幻灯片吧。
    jesse0628
        6
    jesse0628  
       2012-05-09 11:43:13 +08:00   1
    跟楼主体会完全一样,我一直找不到原因,为什么我的添加到scroll view里面的东西会滚起来那么卡,原因大概还是我里面用了很多CALayer圆角的东西,也做了一些CALayer比如绘制什么的操作。但是应该最大的问题是圆角引起的。
    senopanas
        7
    senopanas  
       2012-05-09 11:45:14 +08:00   1
    clipsToBounds=YES实际上还多了一个step跳转到masksToBounds=YES,效果当然都一样:
    -(BOOL)[UIView(Rendering) clipsToBounds]
    +0 3091938a 55 pushl %ebp
    +1 3091938b 89e5 movl %esp,%ebp
    +3 3091938d e800000000 calll 0x30919392
    +8 30919392 59 popl %ecx
    +9 30919393 8b4508 movl 0x08(%ebp),%eax
    +12 30919396 8b5004 movl 0x04(%eax),%edx (CALayer)_layer
    +15 30919399 8b8186cb1301 movl 0x0113cb86(%ecx),%eax masksToBounds
    +21 3091939f 89450c movl %eax,0x0c(%ebp)
    +24 309193a2 895508 movl %edx,0x08(%ebp)
    +27 309193a5 c9 leave
    +28 309193a6 e92e211801 jmpl 0x31a9b4d9

    不过至少可以省一步,shouldResterize效果不大但是有效果。一般来说在cell上添加一个CAlayer的圆角并且masksToBounds也不会降低多少performance,你的头像图片是lazy loading吗?
    mr_pppoe
        8
    mr_pppoe  
       2012-05-09 11:59:42 +08:00   1
    隐约记得有一段WWDC的视频讨论了类似的问题
    adow
        9
    adow  
    OP
       2012-05-09 12:01:02 +08:00
    @senopanas 头像是异步http下载的,我现在是下载完后处理成圆角的UIImage后赋值到imgAvator.image上
    adow
        10
    adow  
    OP
       2012-05-09 12:04:07 +08:00
    哦对了,实际运行中,因为头像部分的http请求做了缓存,所以大部分是本地读取的文件,跳过http请求的
    elden
        11
    elden  
       2012-05-09 12:30:58 +08:00   1
    直接设置cornerRadius会影响滚动的流畅性。如果cell不使用复杂背景,那可以在头像上覆盖一层空心的圆角图片。
    ultragtx
        12
    ultragtx  
       2012-05-09 12:45:08 +08:00   3
    CALayer直接setCornerRadius会发生offscreen rendering,简单地说就是在屏幕外渲染一遍,接着再渲染到屏幕上(涉及到多开一个屏幕外buffer,屏幕内buffer和屏幕外buffer来回切换等问题),CoreAnimation是逐帧渲染的,所以scroll的时候每帧都进行这个操作,结果就很慢,解决方法一般就是先把圆角图片画出来。
    一楼Sai那个方法就是缓存offscreen render,这样就不用每帧都渲染一遍,但是要求layer的内容是不变的,如果有变化还是要慢,不过你这个情况应该符合。

    具体参考WWDC 2011 Session 121 这个讲的特别细
    adow
        13
    adow  
    OP
       2012-05-09 12:52:27 +08:00
    感谢大家的讨论,我之前一直都不知道这些。
    keakon
        14
    keakon  
       2012-05-11 20:55:36 +08:00   1
    最好不要用 UIImageView 和 CALayer,比直接显示肯定要慢的。另外可以用预渲染:
    http://www.keakon.net/article/96200
    http://www.keakon.net/article/98200
    hydyy
        15
    hydyy  
       2012-12-07 21:56:10 +08:00
    哈喽~ 楼主您解决这个问题了嘛? 我也遇到了~~哈哈阿红
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3131 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 22ms UTC 11:50 PVG 19:50 LAX 04:50 JFK 07:50
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86