iOS中如何优雅的添加圆角和边框?

  因为项目需要,整理了下圆角和边框辅助类。想起前几天标哥还在微博里问圆角在tableView里卡顿的问题,想着去炫耀下。去到标哥的博客,发现已经有一定程度解决给出开源库并且在推广,迭代了好几个版本了。。

  圆角这东西被无数性能追求者津津乐道,无数小白们高山仰止。 至于圆角的几种实现方案,设置cornerRadius、加maskLayer、直接加镂空图、内存异步裁剪等等,网络上一搜一大把,这里就不再重复了。这里有两点要提醒下,纹理裁剪才是off-screen rendering的原因,而不是设置圆角。当然你要是作死的去设了layer的fillColor,再来设圆角,那就只能说no zuo no die ;另外在使用光栅化时,一定要设置scale以适配屏幕分辨率。

  既然标哥都给出开源方案了,那就比较一下,检查下自己的不足吧。为参照相同的运行条件,笔者把自己写的辅助类放到标哥的Demo里,实现相同的效果。然后设计思路、外观呈现、CPU和内存、帧速、代码量、侵入性和易用性、适用场景等个方面做出比较。

  标哥的开源库:https://github.com/CoderJackyHuang/HYBImageCliped

  笔者fork后修改的项目:https://github.com/1962449521/HYBImageCliped

  该功能类的在线维护:https://github.com/1962449521/WHUCornerMaker

  笔者整理中的辅助类集:https://github.com/1962449521/WHUKit/tree/master/WHUKitDemo/WHUKitDemo/WHUKit

 

  以下为笔者方案标哥开源库的比较

  一、 突破口的选择

  标哥选择的起点是内存中剪裁图片,通过缓存策略优化性能,给UIView、UIImageView、UIButton等控件增加Category以扩展功能。笔者选择的起点是绘制镂空图,同样使用了缓存以提高复用。因为长期开发SDK尽量不使用Category的习惯,笔者采用辅助类的形式提供功能实现

  二、 功能及解决问题

  主要的出发点都是为了解决圆角图片离屏渲染影响滑动帧速的问题。标哥采用了剪裁图片的方式,能够适应背景非单色情况;在控件内部的图片,能提供圆角效果,比如按钮内非抵边的image;在边线的绘制上,提供了形状边框,边框有填充和边线。笔者提供的辅助类只适用背景单色,裁剪针对UIView或其子类整体,边线只提供单线。

  三、 外观呈现

   除了双色边线外,其它的外观都能做到相同的效果。

标哥静态容器 笔者静态容器
标哥collectionView 笔者collectionView

  

  四、CPU和内存  

  标哥方案CPU使用骤增,最高达到82%。内存使用也高于笔者。因为笔者采用了每次cell出现时重绘边角,所以CPU略高。如果确定每次cell重用时边角位置正确,可以不重绘边角,CPU能稳定在13%左右。图片相对较少,内存使用差别不明显。当不同图片较多时,标哥使用方案需大量缓存裁切好的图片,猜测会在内存使用上随之增加。而笔者方案会复用相同角度颜色的边角,图片增多时不会增加圆角图片的内存开销。

标哥方案
笔者方案

  

  五、 帧速

  滑动帧速基本相近,都有较好的体验,笔者方案数值相对较高。

标哥方案
笔者方案

    六、代码量

  标哥使用了一个管理类HYBImageClipedManager,以及提供了UIImage、UIView、UIButton三个类的category,总共约1千行代码。笔者提供了WHUCornerMaker、WHUBorderMaker两个辅助功能类,约250行代码。

    七、侵入性和易用性

  以下为笔者两个辅助类的头文件声明和暴露的使用API,自认为还是较为清晰易用的。这里要说到关于注释,多余的注释是违反DRY原则的,不过由于国人对英文的理解不直接或者项目编码约定,而加了许多不必要的注释。还是应当以清晰符合语义的方法、变量命名作为首选。至于标哥提供的接入设计,方法太多就不在这里列出了,感兴趣的童鞋可以从本文提供的链接跳入查看^^

@interface WHUCornerMaker : NSObject

+ (BOOL) isCorneredAtView:(UIView * _Nonnull)view;

// 优先选取view 沿superview上的父类容器的背景色, 如果一直为nil, 则取defaultColor 作为圆角颜色

- (void) roundView:( UIView * _Nonnull ) view withCornerRadius:(CGFloat) radius defaultColor:( UIColor * _Nullable)color;

- (void) roundViews:(NSArray<UIView *> * _Nonnull) views withCornerRadius:(CGFloat) radius  defaultColor:( UIColor * _Nullable)color;

- (void) roundView:(UIView * _Nonnull) view withCornerRadius:(CGFloat) radius defaultColor:( UIColor * _Nullable)color byRoundingCorners:(UIRectCorner)corners;

- (void) roundViews:(NSArray<UIView *> * _Nonnull) views withCornerRadius:(CGFloat) radius  defaultColor:( UIColor * _Nullable)color  byRoundingCorners:(UIRectCorner)corners;


@end
@interface WHUBorderMaker : NSObject

+ (void) borderView:( UIView * _Nonnull ) view withCornerRadius:(CGFloat) radius (CGFloat)borderWidth color:(UIColor * _Nonnull)borderColor;


+ (void) borderView:( UIView * _Nonnull ) view withCornerRadius:(CGFloat) radius (CGFloat)borderWidth color:(UIColor * _Nonnull)borderColor byRoundingCorners:(UIRectCorner)corners;

@end

     八、适用场景

  不可否认,标哥提供了更多功能,比如拿到裁切的图片,绘制双色边框等。不过这样的使用场景应该是较少的,笔者提供了辅助类能满足大多数场景的需求。

     九、总结

  在做通用性开源库的时候,可能会考虑更多的东西。但花80%的精力去实现5%使用者的需求是否有必要是有待斟酌的。在笔者方案和标哥方案的比较中,总体而言笔者的方案性能是高出很多,并不随使用条件复杂性的增加而性能降低。这一方面是内存裁剪图片本就是骑虎难下的选择,一方面也是笔者只针对有限的使用场景和需求。

 

原文地址:https://www.cnblogs.com/hushuai-ios/p/5366395.html