Swift 结构体

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)

常见面试题

  1. 结构体赋值会发生什么?
    → 深拷贝(值复制),两个独立实例。
  2. mutating 关键字的作用?
    → 允许方法修改结构体属性。
  3. 为什么 String, Array, Dictionary 是结构体?
    → 值语义更安全、高效,适合复制。

如需深入探讨 泛型结构体属性包装器(@propertyWrapper)Copy-on-Write 优化 等高级话题,欢迎继续提问!

文章已创建 2481

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部