在Swift中,有两种主要的数据类型:值类型和引用类型。
struct)、枚举(enum)和基本类型,如Int、Double、Bool。在传递或赋值时,值会被复制,也就是说对副本的修改不会影响原始值。class)及相关类型。在传递时,复制的不是对象本身,而是对它的引用,因此通过一个引用所做的更改在其他引用中也是可见的。何时使用:
CGPoint、CGSize,不应共享状态的模型),请使用值类型。示例:
struct Point { var x: Int var y: Int } class Person { var name: String init(name: String) { self.name = name } } var p1 = Point(x: 0, y: 0) var p2 = p1 p2.x = 10 // p1.x 会保持为 0 var person1 = Person(name: "Alex") var person2 = person1 person2.name = "Sam" // person1.name 也会变成 "Sam"
let用于struct和class有什么区别?通过let创建的class实例是否完全不可变?
回答:
对于值类型(struct),let使对象及其属性不可变。
对于引用类型(class),let禁止重赋值引用,但不保护对象的属性。如果属性不是在类内部声明为let,则可以进行更改。
示例:
class Box { var value: Int init(value: Int) { self.value = value } } let box = Box(value: 10) box.value = 20 // 好! // box = Box(value: 30) // 错误:无法重赋值box
故事
在支付应用程序中,交易模型被定义为类,尽管不应有状态。出现了一个bug:在同时处理交易列表时,发生了不同界面部分数据的不可预知编辑。决定将模型转换为struct,以便每个组件都处理自己的副本。
故事
在项目中,用户设置存储在类中,以为传递时会复制值。在数据更改时,一个屏幕意外影响了另一个屏幕,因为它们都在操作同一个对象的引用。
故事
在序列化模块中,模型数据被声明为引用类型,因此任何更改都会导致缓存中的状态损坏。更换为值类型后,问题得到解决:数据在每次操作时都是独立的。