Swift 中的结构体(Struct)是值类型(Value Type),用于封装相关的数据和行为。它是 Swift 中构建自定义数据类型的基础之一,广泛用于模型、配置、坐标等场景。
基本语法
struct 结构体名 {
// 属性
var property1: Type
let property2: Type
// 方法
func method() { ... }
mutating func mutatingMethod() { ... }
}
示例:点(Point)
struct Point {
var x: Double
var y: Double
// 自定义初始化器
init(x: Double, y: Double) {
self.x = x
self.y = y
}
// 计算属性
var distanceFromOrigin: Double {
return (x * x + y * y).squareRoot()
}
// 实例方法
func isInFirstQuadrant() -> Bool {
return x > 0 && y > 0
}
// 可变方法(修改属性)
mutating func moveBy(x deltaX: Double, y deltaY: Double) {
self.x += deltaX
self.y += deltaY
}
}
var p = Point(x: 3, y: 4)
print(p.distanceFromOrigin) // 5.0
p.moveBy(x: 1, y: -1)
print(p.x, p.y) // 4.0 3.0
关键特性
| 特性 | 说明 |
|---|---|
| 值类型 | 赋值、传参时会复制(Copy-on-Write 优化) |
| 自动成员初始化器 | 未自定义 init 时,自动生成 |
| mutating | 修改 self 的方法必须标记 |
| 无继承 | 结构体不能继承其他结构体 |
| 协议支持 | 可遵守协议(如 Equatable, Codable) |
1. 自动成员初始化器
struct Size {
var width: Double
var height: Double
}
// 自动生成 init(width:height:)
let size = Size(width: 100, height: 50)
自定义
init后,自动初始化器失效,除非手动实现。
2. 默认初始化器(全默认值)
struct Color {
var red = 0.0
var green = 0.0
var blue = 0.0
}
// 可直接无参初始化
let clear = Color()
3. mutating 方法
struct Counter {
var count = 0
mutating func increment() {
count += 1
}
}
var counter = Counter()
counter.increment() // OK
let常量结构体不能调用mutating方法。
4. 结构体 vs 类(对比)
| 特性 | 结构体 | 类 |
|---|---|---|
| 类型 | 值类型 | 引用类型 |
| 复制 | 复制副本 | 共享引用 |
| 继承 | 不支持 | 支持 |
| 生命周期 | 栈(小)/堆(大) | 堆 + ARC |
| 线程安全 | 高(复制隔离) | 需手动处理 |
| 性能 | 通常更快(无引用计数) | 稍慢(引用计数) |
5. 协议扩展:自动 Equatable
struct Person: Equatable {
var name: String
var age: Int
}
// 自动生成 ==(所有属性相等)
let p1 = Person(name: "Alice", age: 25)
let p2 = Person(name: "Alice", age: 25)
print(p1 == p2) // true
所有属性都遵守
Equatable时,编译器自动合成。
6. Codable 结构体(JSON 解析)
struct User: Codable {
var id: Int
var name: String
var email: String?
// 可自定义键名
enum CodingKeys: String, CodingKey {
case id
case name = "full_name"
case email
}
}
let json = """
{
"id": 1,
"full_name": "Tom",
"email": "tom@example.com"
}
""".data(using: .utf8)!
let decoder = JSONDecoder()
if let user = try? decoder.decode(User.self, from: json) {
print(user.name) // Tom
}
7. 属性观察器
struct StepCounter {
var totalSteps: Int = 0 {
willSet {
print("将要设置为 \(newValue)")
}
didSet {
print("增加了 \(totalSteps - oldValue) 步")
}
}
}
var step = StepCounter()
step.totalSteps = 100
// 将要设置为 100
// 增加了 100 步
8. 延迟存储属性(lazy)
struct DataManager {
lazy var importer = DataImporter() // 首次访问时初始化
var data: [String] = []
}
struct DataImporter {
init() { print("导入数据...") }
}
var manager = DataManager()
manager.data.append("Some data")
// 此时还未触发 importer 初始化
manager.importer // 打印 "导入数据..."
9. 静态属性和方法
struct Math {
static let pi = 3.14159
static func add(_ a: Int, _ b: Int) -> Int {
return a + b
}
}
print(Math.pi) // 3.14159
print(Math.add(2, 3)) // 5
10. 结构体嵌套
struct Matrix {
var data: [[Double]]
struct Size {
var rows: Int
var columns: Int
}
var size: Size {
return Size(rows: data.count, columns: data[0].count)
}
}
let m = Matrix(data: [[1,2], [3,4]])
print(m.size.rows) // 2
最佳实践总结
| 场景 | 推荐使用 |
|---|---|
简单数据模型(如 Point, Size, Color) | 结构体 |
| 需要复制语义 | 结构体 |
| 无继承需求 | 结构体 |
| 性能敏感 | 结构体 |
需要共享、继承、身份比较(===) | 类 |
小技巧
// 快速复制并修改(函数式风格)
struct Player {
var name: String
var score: Int
}
var player = Player(name: "Alex", score: 100)
let updated = Player(name: player.name, score: player.score + 10)
// Swift 5.9+:宏简化
@Copyable
struct Game {
var score: Int
var level: Int
}
var game = Game(score: 100, level: 1)
let next = game.copying(\.score, to: 150)
常见面试题
- 结构体赋值会发生什么?
→ 深拷贝(值复制),两个独立实例。 mutating关键字的作用?
→ 允许方法修改结构体属性。- 为什么
String,Array,Dictionary是结构体?
→ 值语义更安全、高效,适合复制。
如需深入探讨 泛型结构体、属性包装器(@propertyWrapper)、Copy-on-Write 优化 等高级话题,欢迎继续提问!