编程iOS开发者

解释Swift中值类型和引用类型之间的区别。何时应该使用每种类型?

用 Hintsage AI 助手通过面试

回答。

在Swift中,有两种主要的数据类型:值类型引用类型

  • 值类型。 包括结构体(struct)、枚举(enum)和基本类型,如IntDoubleBool。在传递或赋值时,值会被复制,也就是说对副本的修改不会影响原始值。
  • 引用类型。 这包括类(class)及相关类型。在传递时,复制的不是对象本身,而是对它的引用,因此通过一个引用所做的更改在其他引用中也是可见的。

何时使用:

  • 如果您希望数据是独立的副本(例如,CGPointCGSize,不应共享状态的模型),请使用值类型。
  • 如果需要在对象之间共享状态(例如,管理器、控制器、服务),则引用类型更合适。

示例:

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,以便每个组件都处理自己的副本。


故事

在项目中,用户设置存储在类中,以为传递时会复制值。在数据更改时,一个屏幕意外影响了另一个屏幕,因为它们都在操作同一个对象的引用。


故事

在序列化模块中,模型数据被声明为引用类型,因此任何更改都会导致缓存中的状态损坏。更换为值类型后,问题得到解决:数据在每次操作时都是独立的。