大话PaintCode
– 金蛇郎君
为什么要使用PaintCode
我是一个iOS开发者,为什么要使用PaintCode
这个工具?首先,我们要了解PaintCode
是干什么的,总的来说,就是可以通过可视化设计,来生成Swift
或Objective C
代码,目前PaintCode3
系列开始支持Java了,同时也还支持一些其他的语言,如下图:
不过这里只讨论iOS方面,而且只针对iPhone。用PNG图片来制作用户界面是没有沉闷的,不能解决设备的分辨率问题,因此你必须要提供格式的图片,比如 1倍图,2倍图,3倍图 iOS规范 ,图形的放大和缩小等,如果利用PNG的图片不经过处理的话,是做不到的。
一个比用图片好的方法就是通过Objective-C
或者Swift
代码来绘制界面。代码能够解决iPhone
各种设备的分辨率问题,不幸的是,写代码非常烦闷。PaintCode
这时候就非常有用了,她是一款矢量绘图工具软件,可以直接将设计的矢量图形直接转化为Objective-C
或者Swift
代码,这些代码如果是我们手写的话,可能会需要一整天时间。PaintCode
将会导出所有绘制的图形到一个类中,这里以Swift
为例子。我们称这个类,为 StyleKit
,值得说明的是,PaintCode可以修改图形后重新计算Swift
代码。
如果你已经有矢量图标,你可以轻松导入SVG,PSD,PDF,EPS
已经AI文件到 PaintCode
,甚至可以在Sketch中直接 copy
& paste
。是不是很方便呢?你想采用基于代码的方式来绘制交互界面,没必要一开始就全部用代码方式创建,可以选择性的有需要的地方采用代码方式来绘制界面,其他地方可以继续使用PNG图片进行设置使用。PaintCode
这款Mac
系统下的软件本身,除了程序应用图标以为,其他全部是采用代码的方式绘制的。即使你现在只是在某些界面使用代码动态绘制,也会为你节约不上编码的时间!所以,为什么不用PaintCode
呢?
- 还有一个问题,有些人觉得通过自定义
UIView
复写DrawRect
方法,有寄宿图消耗大内存问题。这里,关于这个发表下自己的个人看法。
实际上也做了一些调查,首先去官网下载第一个Demo
运行,修改项目Target为通用,iPad air2
运行,- (void)drawRect: (CGRect)rect
方法里面,rect
宽高为屏幕宽高(修改了默认项目视图约束)。(注意:由于视图通过故事版创建,有固定的约束,rect值不会变化,除非更改视图约束) 以下在rect同一大小下面做了多个自定义视图覆盖的测试流程,APP运行占用内存大小通过instruments工具的Allocations功能查看。
上面的测试,是在比较极端的情况下,差不多接近air2全屏的大小,这里大小打印出来
{744, 984}
,根据寄宿图大小公式M = width(px) * height(px) * perPixe(单位像素占用内存字节大小:默认4字节)
,则(744(pt) * 2)(px) * (984(pt) * 2)(px) * 4(单位像素占用内存字节大小) = 11713536
,M = 11713536 / 1024 / 1024 = 11.17 Mb
,而测试数据中,每新增加一个和屏幕差不多等宽高的自定义视图,内存大小增加11Mb左右,计算的值和实际值十分接近!之前看过其他的博客有谈到计算寄宿图大小的问题,但是没看到过一个将公式讲解清楚的,有个问题,单位像素占用内存字节大小,这里取4,怎么来的呢?凡是涉及到的文章都没有说明这个参数的含义,有的计算公式还是错误的,经过我的一番求证。大概,证实如下:perPixe:表示单位像素占用内存字节大小,这个值和很多因素有关,比如颜色灰度,是否被压缩等,这个可以通过一种方式来简单获取这个值,看下面代码:/// MARK:- 绘图 - (void)drawRect: (CGRect)rect { NSLog(@"寄宿图大小:%@\n",NSStringFromCGRect(rect)); UIGraphicsBeginImageContextWithOptions(rect.size, false, 2.0); CGImageRef imageRef = UIGraphicsGetImageFromCurrentImageContext().CGImage; printf("一像素占用内存大小:%zu bit\n",CGImageGetBitsPerPixel(imageRef)); [MyStyleKit drawRateButtonWithFrame: CGRectMake(0, 0, 2048/2*4, 2732/2*4)]; // 寄宿图大小计算公式:M = width(px)* height(px)* perPixel(单位像素占用内存大小:字节),1byte = 8bit }
实际上就是
CGImageGetBitsPerPixel
方法返回单位像素占用内存大小的值,这个打印出来为32bit = 4byte!相信这个问题已经解释清楚了,都明白了。另外需要说明,一个问题,[MyStyleKit drawRateButtonWithFrame: CGRectMake(0, 0, 2048/2*4, 2732/2*4)];
大家都知道软件绘制行为要比GPU合成要慢而且还需要更多的内存空间,如果视图通过代码创建大小设置为屏幕宽度3倍:ButtonView *buttonView = [[ButtonView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth([[UIScreen mainScreen] bounds]) * 3, CGRectGetHeight([[UIScreen mainScreen] bounds]) * 3)]; buttonView.backgroundColor = [UIColor whiteColor]; [self.view addSubview:buttonView];
总结
- 上图中可以看出,内存增加到114MB,有点大了,所以类似大图是不适合这种绘制的,不过这么大的图,也没必要我们通过此种方式来进行绘制,消耗CPU性能。
- 用自定义的类文件来代替图片,可以减少APP安装包的体积,不过在运行中会增加一些多余的内存消耗,特别是在加载接近全屏的自定义视图的时候。
- 用代码绘制方式创建图形可以避免1、2、3倍图的干扰,无需再使用多种类型图片进行适配UI。
- 团队使用的话,对程序员和UI设计要求都比较高一点,怎样配合很重要,整个流程怎么走。这要求,UI设计师,导出来的是矢量图型,最好用PaintCode直接进行绘制,涉及到视图根据传入Frame值进行绘制的情况,设计者和程序员需要沟通,官方推荐UI设计师用Mac系统下的一款Sketch软件,开发了相应插件,可以直接导出到PaintCode。PaintCode的功能,还远不止于此,想要了解更多的知识,请到 PaintCode官网 查看。
- 一个界面绘制图标不会太多,并且图标大小不会过大,鉴于能减少APP体积,解决图片倍率问题等方面,还是值得我们开发者学习和使用的。
- 附上demo的github地址:DynamicShapesBasics_ObjectiveC,更改过几次,因此只保留了最后一次的情况!
=============================
2017-01-04补充
关于视图大图的情况,用CATiledLayer处理,这里有篇文章:
http://blog.sina.com.cn/s/blog_7192ec8e0100qz8m.html
http://www.jianshu.com/p/ee5502a1aad3
大家可以自行搜索下相关方法!