Swift 结构体:从入门到实战
1. 引言在 Swift 中结构体Struct是构建数据模型和高性能代码的核心工具。与类不同结构体是值类型这意味着它在赋值和传递时会被复制从而避免共享状态带来的复杂性。本文将带你深入理解 Swift 结构体的定义、初始化、属性、方法、扩展及其与类的对比并通过丰富的代码实例帮助你快速掌握。2. 结构体的基本定义使用struct关键字即可定义一个结构体内部可以声明存储属性struct Point { var x: Double var y: Double } let origin Point(x: 0, y: 0) print(origin.x) // 0.0结构体会自动获得一个“成员逐一初始化器”Memberwise Initializer可以按属性名传入初始值。3. 初始化方法虽然默认的成员初始化器很方便但很多时候我们需要自定义初始化逻辑。struct Rectangle { var width: Double var height: Double // 自定义初始化器 init(squareSide side: Double) { width side height side } } let square Rectangle(squareSide: 10) // square.width 和 square.height 都是 10还可以添加可失败初始化器或带默认值的属性struct Car { var brand: String var year: Int init?(brand: String, year: Int) { guard !brand.isEmpty, year 1885 else { return nil } self.brand brand self.year year } }4. 结构体是值类型结构体赋值或传递给函数时会进行深拷贝。修改一个变量不会影响另一个struct Point { var x 0, y 0 } var p1 Point(x: 1, y: 2) var p2 p1 // 拷贝 p2.x 10 print(p1.x) // 1 print(p2.x) // 10而类是引用类型共享同一实例。这是结构体和类最本质的区别也是 Swift 推荐优先使用结构体的原因之一。5. 属性和方法5.1 存储属性与计算属性结构体可以拥有存储属性和计算属性计算属性不直接存储值而是通过 get/set 提供struct Circle { var radius: Double var diameter: Double { get { return radius * 2 } set { radius newValue / 2 } } }5.2 属性观察器可以为存储属性添加willSet和didSetstruct StepCounter { var totalSteps: Int 0 { willSet { print(将步数设置为 \(newValue)) } didSet { if totalSteps oldValue { print(增加了 \(totalSteps - oldValue) 步) } } } }5.3 方法结构体内部可以定义实例方法和类型方法struct Vector2D { var x 0.0, y 0.0 func length() - Double { return sqrt(x * x y * y) } static func unitX() - Vector2D { return Vector2D(x: 1, y: 0) } }5.4 mutating 方法默认情况下结构体实例方法不能修改实例的属性。如果需要修改必须在方法前添加mutating关键字struct Point { var x 0.0, y 0.0 mutating func moveBy(dx: Double, dy: Double) { x dx y dy } } var point Point(x: 1, y: 1) point.moveBy(dx: 2, dy: 3) // 现在 point 的坐标为 (3, 4)6. 下标结构体可以定义下标subscript方便通过索引访问内部数据struct TimesTable { let multiplier: Int subscript(index: Int) - Int { return multiplier * index } } let threeTimesTable TimesTable(multiplier: 3) print(threeTimesTable[6]) // 187. 嵌套类型结构体内部可以嵌套枚举、结构体或类形成更清晰的层级结构struct ChessBoard { enum Piece { case king, queen, rook, bishop, knight, pawn } struct Square { var row: Int var column: Int var piece: Piece? } var squares: [[Square]] [] }8. 结构体的扩展通过扩展Extension可以为已有结构体添加新功能甚至可以扩展 Swift 标准库中的结构体extension Point { // 添加计算属性 var isOrigin: Bool { return x 0 y 0 } // 添加方法 func distance(to other: Point) - Double { let dx x - other.x let dy y - other.y return sqrt(dx * dx dy * dy) } }9. 遵循协议结构体可以遵循一个或多个协议例如Equatable、Hashable、Codable从而获得相等性比较、哈希、编解码等能力struct Person: Codable, Equatable { var name: String var age: Int } let alice Person(name: Alice, age: 30) let encoder JSONEncoder() let data try encoder.encode(alice)10. 结构体与类的对比总结特性结构体类类型值类型引用类型继承不支持支持类型转换不支持支持is/as?析构函数无有deinit引用计数无有 ARC可变性实例常量不可变方法需mutating实例常量可修改属性使用建议优先用于数据模型、数值类型等需要继承或共享状态时使用11. 实战示例构建用户信息模型下面演示如何用结构体构建一个用户管理系统的数据模型并结合计算属性和 Codable 协议进行数据持久化struct Address: Codable { var street: String var city: String var zipCode: String } struct User: Codable, Equatable { var id: Int var name: String var email: String var address: Address var displayName: String { return \(name) (#\(id)) } static func loadFromDisk() throws - [User] { let url FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] .appendingPathComponent(users.json) let data try Data(contentsOf: url) return try JSONDecoder().decode([User].self, from: data) } }这个模型可以直接用于 JSON 解析和本地存储充分体现了结构体在 Swift 开发中的便利性。12. 结语Swift 结构体是构建安全、高效代码的基石。理解其值语义、初始化器、属性和方法、扩展以及与协议的配合能帮助你写出更健壮的 iOS 或服务端 Swift 程序。希望本文的代码实例能为你提供实用的参考。