随着Swift的日渐成熟和给开发过程带来的便利性及安全性,京喜App中的原生业务模块和基础模块使用Swift开发占比逐渐增高。本次讨论的是struct对比Class的一些优劣势,重点分析对包体积带来的影响及规避措施。
作者:京东零售邓立兵一、基础知识1、类型对比引用类型:将一个对象赋值给另一个对象时,系统不会对此对象进行拷贝,而会将指向这个对象的指针赋值给另一个对象,当修改其中一个对象的值时,另一个对象的值会随之改变。
值类型:将一个对象赋值给另一个对象时,会对此对象进行拷贝,复制出一份副本给另一个对象,在修改其中一个对象的值时,不影响另外一个对象。。Swift中的
两者的区别可以查阅Apple官方文档
2、Swift中struct和Class区别1、class是引用类型、struct是值类型2、类允许被继承,结构体不允许被继承、类中的每一个成员变量都必须被初始化,否则编译器会报错,而结构体不需要,编译器会自动帮我们生成init函数,给变量赋一个默认值4、当你需要继承Objective-C某些类的的时候使用class5、class声明的方法修改属性不需要`mutating`关键字;struct需要6、如果需要保证数据的唯一性,或者保证在多线程数据安全,可以使用struct;而希望创建共享的、可变的状态使用class
以上三点可以参考深入理解Swift中的Class和Struct进行更多细节的阅读学习
二、struct优选孔子曰:择其善者而从之,其不善者而改之。
1、安全性使用struct是值类型,在传递值的时候它会进行值的copy,所以在多线程是安全的。无论你从哪个线程去访问你的Struct,都非常简单。2、效率性
struct存储在stack中(这比malloc/free调用的性能要高得多),class存储在heap中,struct更快。、内存泄露
没有引用计数器,所以不会因为循环引用导致内存泄漏
基于这些因素,在日常开发中,我们能用struct的我们尽量使用struct。
三、struct的不完美孟子曰:鱼,我所欲也,熊掌亦我所欲也;二者不可得兼。
“熊掌”再好,吃多了也难以消化。特别在中大型项目中,如果没有节制的使用struct,可能会带来意想不到的问题。
1、内存问题值类型有哪些问题?比如在两个struct赋值操作时,可能会发现如下问题:
1、内存中可能存在两个巨大的数组;2、两个数组数据是一样的;、重复的复制。
解决方案:COW(copy-on-write)机制
1、Copy-on-Write是一种用来优化占用内存大的值类型的拷贝操作的机制。2、对于Int,Double,String等基本类型的值类型,它们在赋值的时候就会发生拷贝。(内存增加)、对于Array、Dictionary、Set类型,当它们赋值的时候不会发生拷贝,只有在修改的之后才会发生拷贝。(内存按需延时增加)4、对于自定义的数据类型不会自动实现COW,可按需实现。
那么自定义的数据如何实现COW呢,可以参考官方代码:
/*我们使用class,这是一个引用类型,因为当我们将引用类型分配给另一个时,两个变量将共享同一个实例,而不是像值类型一样复制它。*/finalclassRef{varval:Tinit(_v:T){val=v}}/*创建一个struct包装Ref:由于struct是一个值类型,当我们将它分配给另一个变量时,它的值被复制,而属性ref的实例仍由两个副本共享,因为它是一个引用类型。然后,我们第一次更改两个Box变量的值时,我们创建了一个新的ref实例,这要归功于:isUniquelyReferencedNonObjC这样,两个Box变量不再共享相同的ref实例。*/structBox{varref:Refinit(_x:T){ref=Ref(x)}varvalue:T{get{returnref.val}set{//isKnownUniquelyReferenced函数来检查某个引用只有一个持有者//如果你将一个Swift类的实例传递给这个函数,并且没有其他变量强引用这个对象的话,函数将返回true。如果还有其他的强引用,则返回false。不过,对于Objective-C的类,它会直接返回false。if(!isUniquelyReferencedNonObjC(ref)){ref=Ref(newValue)return}ref.val=newValue}}}//ThiscodewasanexampletakenfromtheswiftrepodocfileOptimizationTips//Link: