Swift 基础知识(一)

一、Swift 中 类(class) 和 结构体(struct) 的区别,以及各自优缺点?

核心区别

特性 类(Class) 结构体(Struct)
类型 引用类型(传递时共享内存) 值类型(传递时复制新实例)
存储位置 堆内存 栈内存(若包含引用类型属性,其数据仍在堆内存)
继承 支持(除非用 final 修饰) 不支持
类型转换 支持运行时类型检查(is/as 仅编译时类型检查
内存管理 引用计数(ARC) 自动栈内存释放(无需引用计数)
方法派发 动态派发(运行时确定方法地址) 静态派发(编译时确定方法地址)
析构函数 支持 deinit 不支持
线程安全 需手动处理(共享内存) 天然线程安全(值隔离)

赋值行为的本质

  • 类(浅拷贝)

    赋值时复制指针,新旧变量指向同一内存地址。修改任一变量会影响所有引用。

    swift 复制代码
    class Person {
        var name: String
        init(name: String) { self.name = name }
    }
    let p1 = Person(name: "Alice")
    let p2 = p1
    p2.name = "Bob"
    print(p1.name) // 输出 "Bob"
  • 结构体(深拷贝)

    赋值时复制值,新旧变量独立存储。修改一个不会影响另一个。

    swift 复制代码
    struct Point {
        var x: Int
        var y: Int
    }
    var p1 = Point(x: 1, y: 2)
    var p2 = p1
    p2.x = 3
    print(p1.x) // 输出 1

优缺点分析

类(Class)的优点
  1. 共享与可变状态:适合需要多个对象共享同一数据的场景(如网络请求管理器)。
  2. 继承与多态:支持面向对象设计,复用代码逻辑。
  3. 运行时动态性:支持类型检查、方法重写和 KVO。
类(Class)的缺点
  1. 内存开销:堆内存分配和引用计数管理增加性能损耗。
  2. 线程安全隐患:共享内存需额外同步机制(如锁、GCD)。
  3. 复杂性 :需处理循环引用(weak/unowned)。
结构体(Struct)的优点
  1. 高性能:栈内存分配速度快,无引用计数开销。
  2. 线程安全:值隔离特性天然避免共享内存冲突。
  3. 清晰所有权:深拷贝行为减少意外副作用。
结构体(Struct)的缺点
  1. 无法继承:不支持继承,复用代码需依赖协议和组合。
  2. 不适合复杂对象:频繁深拷贝大对象可能导致性能问题。

使用场景建议

场景 推荐类型 理由
轻量级数据模型(如坐标、颜色) 结构体 值类型更安全高效,无共享风险
需要继承或共享状态的组件 利用面向对象特性实现复用和动态行为
高频创建的临时对象 结构体 栈内存快速分配释放,减少堆内存压力
需线程安全的数据容器 结构体 值隔离避免竞态条件

补充说明

  1. 结构体中包含引用类型

    若结构体的属性是类实例,深拷贝时仅复制引用(指针),数据仍共享:

    swift 复制代码
    struct Container {
        var ref: NSMutableArray // 引用类型属性
    }
    var c1 = Container(ref: NSMutableArray())
    var c2 = c1
    c2.ref.add("Test") // c1.ref 也会被修改
  2. 协议与扩展

    结构体和类均可遵循协议并使用扩展,但结构体无法通过继承实现多态。

  3. Copy-on-Write 优化

    Swift 标准库中的集合类型(如 ArrayDictionary)对结构体实现了写时复制,避免不必要的深拷贝。


官方建议

Apple 在 Swift 官方文档 中明确推荐:

优先使用结构体,除非你需要类独有的特性(如继承、析构函数或引用语义)。

二、 Swift 中什么是可选类型?

1. 什么是可选类型?

可选类型(Optional)是 Swift 中一种特殊的数据类型,用于表示一个变量可能有值(如 IntString 等),也可能没有值(nil)。它的核心设计目的是强制开发者显式处理值缺失的情况,从而避免空指针异常(Null Pointer Exception),提升代码的安全性。


2. 可选类型的语法

  • 声明可选类型 :在类型后添加 ?

    swift 复制代码
    var name: String?  // 可能为 String 或 nil
    var age: Int?      // 可能为 Int 或 nil
  • 隐式解包可选类型 :在类型后添加 !

    swift 复制代码
    var forcedValue: String!  // 声明时允许为 nil,但使用时假设已赋值

3. 可选类型的本质

可选类型是一个泛型枚举,定义如下:

swift 复制代码
public enum Optional<Wrapped> {
    case none       // 无值(nil)
    case some(Wrapped) // 有值(Wrapped 类型)
}

例如,String? 实际上是 Optional<String> 的简写。


4. 可选类型的解包方式

(1) 强制解包(Force Unwrap)

使用 ! 强制解包,但如果值为 nil 会触发运行时错误。

swift 复制代码
let name: String? = "Alice"
print(name!) // 输出 "Alice"

let age: Int? = nil
print(age!) // 运行时崩溃!
(2) 可选绑定(Optional Binding)

通过 if letguard let 安全解包:

swift 复制代码
if let unwrappedName = name {
    print("Name is (unwrappedName)")
} else {
    print("Name is nil")
}
(3) 空合并运算符(Nil-Coalescing Operator)

提供默认值:

swift 复制代码
let name = optionalName ?? "Unknown"
(4) 可选链式调用(Optional Chaining)

安全访问属性或方法:

swift 复制代码
let length = user?.name?.count // 若任一环节为 nil,返回 nil

5. 隐式解包可选类型(Implicitly Unwrapped Optional)

  • 用途 :用于变量初始化后一定会被赋值,但声明时可能为 nil 的场景(如 IBOutlet)。
  • 风险 :若访问时仍为 nil,会触发运行时错误。
swift 复制代码
@IBOutlet weak var label: UILabel! // 隐式解包类型

6. 可选类型的优势

  • 安全性 :编译器强制处理 nil 情况,减少崩溃风险。
  • 清晰性:明确标记可能缺失的值,提升代码可读性。
  • 灵活性:与 Swift 的强类型系统结合,支持泛型和模式匹配。

7. 使用场景

  • 网络请求结果 :可能成功(有数据)或失败(nil)。

  • 用户输入处理:如文本框内容可能为空。

  • 类型转换 :尝试将 Any 转换为具体类型时可能失败。

    swift 复制代码
    let value: Any = "123"
    let number = value as? Int // Int?

8. 注意事项

  • 避免滥用 ! :强制解包应仅在确定值非 nil 时使用。
  • 优先使用可选绑定if letguard let 更安全。
  • 合理使用隐式解包:仅用于生命周期明确的变量(如 UI 控件)。

9. 示例代码

swift 复制代码
// 定义一个可能为 nil 的可选类型
var optionalNumber: Int? = 42

// 安全解包
if let number = optionalNumber {
    print("The number is (number)")
} else {
    print("The number is nil")
}

// 空合并运算符
let validNumber = optionalNumber ?? 0

// 可选链式调用
struct Person {
    var address: Address?
}

struct Address {
    var street: String?
}

let person: Person? = Person(address: Address(street: "Main St"))
let street = person?.address?.street // 类型为 String?

10. 总结

可选类型是 Swift 语言的核心特性之一,通过编译时的严格检查,显著提升了代码的健壮性。合理使用可选类型及其解包方式,能有效避免空指针异常,同时使代码逻辑更加清晰可靠。

三、Swift 中什么 是 泛型?

泛型是 Swift 语言中的核心特性之一,允许开发者编写灵活、可重用且类型安全的代码。通过泛型,可以定义适用于多种数据类型的函数、类、结构体或枚举,而无需重复编写相同逻辑的代码。


1. 泛型的基本概念

泛型通过类型参数化 实现,类型参数在定义时作为占位符(如 <T>),在使用时由具体类型替换。例如:

swift 复制代码
// 泛型函数:交换任意类型的两个值
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
    let temp = a
    a = b
    b = temp
}

var x = 5, y = 10
swapTwoValues(&x, &y) // T 被推断为 Int

var str1 = "Hello", str2 = "World"
swapTwoValues(&str1, &str2) // T 被推断为 String

2. 泛型的核心作用

  • 代码复用:同一套逻辑可处理不同类型的数据。
  • 类型安全:编译器在编译时检查类型,避免运行时错误。
  • 性能优化:泛型在编译时生成具体类型的代码,无运行时开销。

3. 泛型的使用场景

(1) 泛型函数

适用于需要处理多种类型的算法(如排序、交换):

swift 复制代码
func findIndex<T: Equatable>(of value: T, in array: [T]) -> Int? {
    for (index, item) in array.enumerated() {
        if item == value { return index }
    }
    return nil
}

let names = ["Alice", "Bob"]
let index = findIndex(of: "Bob", in: names) // 返回 1
(2) 泛型类型

定义可存储任意类型数据的容器(如自定义集合):

swift 复制代码
struct Stack<Element> {
    private var elements = [Element]()
    mutating func push(_ element: Element) {
        elements.append(element)
    }
    mutating func pop() -> Element? {
        elements.popLast()
    }
}

var intStack = Stack<Int>()
intStack.push(1)
intStack.push(2)

var stringStack = Stack<String>()
stringStack.push("Swift")
(3) 泛型协议

通过 associatedtype 定义协议中的关联类型,允许遵循协议的类型自定义具体类型:

swift 复制代码
protocol Container {
    associatedtype Item
    var count: Int { get }
    mutating func append(_ item: Item)
    subscript(i: Int) -> Item { get }
}

struct IntList: Container {
    typealias Item = Int
    private var items = [Int]()
    var count: Int { items.count }
    mutating func append(_ item: Int) {
        items.append(item)
    }
    subscript(i: Int) -> Int { items[i] }
}

4. 泛型约束

限制泛型类型必须满足特定条件(如遵循协议、继承类或实现特定方法):

swift 复制代码
// 约束 T 必须遵循 Comparable 协议
func maxValue<T: Comparable>(_ a: T, _ b: T) -> T {
    return a > b ? a : b
}

// 约束 Key 必须遵循 Hashable,Value 可以是任意类型
struct Dictionary<Key: Hashable, Value> {
    private var storage = [Key: Value]()
    // ...
}

5. 关联类型(Associated Types)

在协议中使用关联类型,定义泛型需求:

swift 复制代码
protocol NetworkService {
    associatedtype Response: Decodable
    func fetchData(completion: @escaping (Result<Response, Error>) -> Void)
}

struct UserService: NetworkService {
    typealias Response = User // 指定具体类型
    func fetchData(completion: @escaping (Result<User, Error>) -> Void) {
        // 网络请求逻辑
    }
}

6. 类型擦除(Type Erasure)

处理需要隐藏具体泛型类型的场景(如返回泛型协议的实例):

swift 复制代码
struct AnyPrinter<T>: Printer {
    private let _print: (T) -> Void
    init<U: Printer>(_ printer: U) where U.T == T {
        _print = printer.print
    }
    func print(_ value: T) {
        _print(value)
    }
}

7. 泛型与标准库

Swift 标准库广泛使用泛型,例如:

  • 集合类型Array<Element>Dictionary<Key, Value>
  • 可选类型Optional<Wrapped>
  • 错误处理Result<Success, Failure>

8. 泛型的优势

  • 减少重复代码:无需为不同类型编写相同逻辑。
  • 增强类型安全:编译器在编译时检查类型错误。
  • 提升性能:无运行时类型转换开销。

9. 总结

场景 示例 核心作用
函数逻辑复用 swapTwoValues<T> 处理多种类型数据
自定义容器 Stack<Element> 存储任意类型元素
协议抽象 Container 协议 + 关联类型 定义灵活的类型需求
类型约束 T: Equatable 确保类型满足特定条件

通过合理使用泛型,开发者可以显著提升代码的灵活性和健壮性,同时减少冗余代码。


四、 Swift 中的 strongweakunowned 详解

1、基本概念

在 Swift 中,strongweakunowned 是用于管理对象引用计数的关键字,与 自动引用计数(ARC) 机制密切相关。它们的核心作用是 控制对象生命周期,避免内存泄漏或野指针问题。

关键字 行为 引用计数 是否可为 nil 安全性
strong 默认修饰符,持有对象时增加引用计数,对象不会被释放。 增加 否(非可选类型) 安全
weak 不增加引用计数,对象释放后自动置为 nil 不增加 是(可选类型) 安全(自动置空)
unowned 不增加引用计数,对象释放后仍保留悬垂指针,访问时可能导致崩溃。 不增加 否(非可选类型) 不安全(需谨慎)

2、核心区别

(1). strong
  • 特点:默认修饰符,持有对象时会增加引用计数,对象生命周期由引用计数控制。

  • 适用场景:大多数情况下使用,表示明确的"拥有关系"。

  • 示例

    swift 复制代码
    class Person {
        var pet: Dog? // 默认是 strong
    }
(2). weak
  • 特点

    • 不增加引用计数,对象释放后自动置为 nil
    • 必须声明为可选类型(var + ?)。
    • 它在对象释放后弱引用也随即消失。继续访问该对象,程序会得到 nil,不会出现崩溃。
  • 适用场景 :打破循环引用,尤其用于 非父子关系 的相互引用(如 delegate)。

  • 示例

    swift 复制代码
    class ViewController: UIViewController {
        weak var delegate: DataDelegate? // 弱引用避免循环
    }
(3). unowned
  • 特点

    • 不增加引用计数,但假设对象在生命周期内始终有效,不会为 nil
    • 非可选类型,访问已释放的对象会导致崩溃。
  • 适用场景 :两个对象生命周期 严格同步,且被引用对象不会先于引用者释放。

  • 示例

    swift 复制代码
    class CreditCard {
        unowned let owner: Customer // Customer 一定比 CreditCard 生命周期长
        init(owner: Customer) {
            self.owner = owner
        }
    }

何时使用 unowned

1. 适用场景
  • 对象生命周期严格绑定
    被引用对象(如 owner)的生命周期 长于或等于 引用者(如 CreditCard)。
  • 避免循环引用且无法使用 weak
    当需要非可选类型且确保对象不会提前释放时。
2. 使用示例
swift 复制代码
class Customer {
    var card: CreditCard?
}

class CreditCard {
    unowned let owner: Customer
    init(owner: Customer) {
        self.owner = owner
    }
}

// 使用
let customer = Customer()
customer.card = CreditCard(owner: customer) // 无循环引用
3. 注意事项
  • 绝对不要滥用:必须确保被引用对象不会被提前释放。
  • 优先选择 weak :若无法确保生命周期同步,优先使用 weak
  • unowned 与弱引用本质上一样。不同的是,unowned 无主引用 实例销毁后仍然存储着实例的内存地址(类似于OC中的unsafe_unretained), 试图在实例销毁后访问无主引用,会产生运行时错误(野指针)
  • weak unowned 只能用在 类实例上面
  • weakunowned 都能解决 循环引用,unowned 要比 weak 性能 稍高
    • 在生命周期中可能会 变成 nil 的使用 weak
    • 初始化赋值以后再也不会变成 nil 使用 unowned

对比 weakunowned

特性 weak unowned
是否可选 必须声明为可选类型(? 非可选类型
安全性 自动置 nil,访问安全 可能触发野指针崩溃
生命周期假设 允许被引用对象提前释放 假设被引用对象始终存在
内存管理 无需手动置 nil 需确保引用对象生命周期

常见问题

1. 循环引用是如何产生的?

当两个对象通过 strong 相互引用时,引用计数无法归零,导致内存泄漏:

swift 复制代码
class A {
    var b: B?
}

class B {
    var a: A?
}

let a = A()
let b = B()
a.b = b // A 强引用 B
b.a = a // B 强引用 A → 循环引用!
2. 如何打破循环引用?
  • 将其中一个引用改为 weakunowned

    swift 复制代码
    class B {
        weak var a: A? // 弱引用打破循环
    }
3. 闭包中的循环引用

闭包捕获外部变量时默认是 strong,需使用捕获列表:

swift 复制代码
class NetworkManager {
    var completion: (() -> Void)?
    
    func fetchData() {
        // 使用 [weak self] 避免循环引用
        someAsyncTask { [weak self] in
            self?.handleData()
        }
    }
}

总结

场景 推荐修饰符 理由
默认对象引用 strong 明确所有权关系
打破父子对象外的循环引用 weak 安全自动置空
严格同步生命周期的对象引用 unowned 避免可选类型解包,需确保对象存活

通过合理使用 strongweakunowned,可以避免内存泄漏和野指针问题,写出更健壮的 Swift 代码。


五、Swift 中 staticclass 关键字对比

核心区别

特性 static class
适用类型 classstructenum class
修饰存储属性 ✅ 允许 ❌ 禁止
修饰计算属性/方法 ✅ 允许 ✅ 允许
是否支持子类重写 ❌ 不可重写(隐含 final ✅ 可重写(需用 override
协议中的使用 协议中统一用 static,所有类型实现 协议中不可用,仅类实现时可选 class

使用场景

  1. static

    • 通用场景 :适用于所有类型(classstructenum)。
    • 存储属性:定义类级别的常量或变量。
    • 禁止重写:明确不希望子类重写的类型方法或属性。
    • 协议定义 :协议中声明类型方法或属性时,必须用 static
  2. class

    • 类专用 :仅用于 class 类型。
    • 允许重写:希望子类重写父类的类型方法或计算属性。
    • 计算属性:定义可被子类重写的类计算属性。

示例代码

swift 复制代码
// 协议定义
protocol MyProtocol {
    static func protocolMethod()  // 协议中必须用 static
}

// 类实现
class Parent: MyProtocol {
    static var storageProperty = "Parent"  // 类存储属性
    class var computedProperty: String { "Parent" }  // 可重写的类计算属性
    class func classMethod() { }          // 可重写的类方法
    static func protocolMethod() { }      // 实现协议方法(隐含 final)
}

class Child: Parent {
    override class var computedProperty: String { "Child" }
    override class func classMethod() { }  // ✅ 允许重写
    // override static func protocolMethod() { }  // ❌ 禁止重写(static隐含final)
}

// 结构体实现
struct MyStruct: MyProtocol {
    static func protocolMethod() { }      // 结构体必须用 static
}

注意事项

  • 存储属性class 不能修饰存储属性(仅 static 可以)。
  • 协议兼容性 :协议中声明类型方法/属性时,使用 static;类实现时可用 classstaticstatic 会隐含 final)。
  • 性能优化static 方法/属性在编译期绑定,效率略高于 class

六、Swift 访问控制总结

Swift 提供了 5 种访问控制级别,用于限制代码中实体(类、属性、方法等)的可见性,确保代码的封装性和安全性。以下是各访问级别的核心区别及使用场景:


1. 访问级别从高到低

关键字 作用范围 允许继承/重写 适用场景
open 跨模块可见,且允许其他模块继承或重写 框架或库的公开 API(如 UIKit)
public 跨模块可见,但禁止其他模块继承或重写(类和成员默认不可继承) 暴露无需继承的工具类、方法
internal 仅当前模块内可见(默认级别) - 模块内部实现细节
fileprivate 仅当前文件内可见 - 文件内共享的辅助函数或类型
private 仅当前作用域(类型或扩展)内可见 - 类型内部的私有实现细节

2. 核心规则

  • 默认访问级别 :未显式指定时,默认为 internal
  • 成员访问限制 :成员的访问级别不能高于其所属类型(如 public classprivate 属性合法,但 private classpublic 属性非法)。
  • 协议一致性 :遵循协议的类型必须满足协议要求的访问级别(如协议声明为 public,则遵循类型也需 public)。
  • 扩展中的访问控制 :扩展默认继承原始类型的访问级别,但可显式指定(如 private extension)。

3. 使用示例

框架开发(跨模块)
swift 复制代码
// Framework 模块
open class NetworkManager {        // 允许其他模块继承
    public static let shared = NetworkManager()
    internal func log() { }        // 仅模块内部可见
    private var token: String?     // 仅当前类可见
}

public struct APIError: Error {    // 其他模块可用,不可继承
    public let code: Int
}
模块内部
swift 复制代码
// App 模块
internal struct User {             // 默认 internal,仅模块内可见
    var name: String
    fileprivate var id: Int        // 同一文件内可见
}

private extension String {         // 扩展内所有成员默认 private
    func trimmed() -> String {
        self.trimmingCharacters(in: .whitespaces)
    }
}

4. 特殊场景

  • 单元测试 :通过 @testable import ModuleName 可访问模块的 internal 实体。
  • 子类重写 :子类方法的访问级别不能低于父类方法(如父类方法为 open,子类可重写为 public,但不能是 internal)。
  • 泛型约束:泛型类型的访问级别需与其类型参数一致或更高。

5. 选择指南

场景 推荐级别 示例
开发第三方框架或库 open/public 公开工具类、核心功能方法
模块内部工具类 internal 数据模型、网络请求封装
文件内共享的辅助函数 fileprivate 同一文件内的 JSON 解析工具
类型内部私有实现 private 缓存属性、敏感数据处理方法

通过合理使用访问控制,可以提升代码的可维护性,减少耦合,同时保护关键实现细节不被外部误用。

七、Swift 写时复制(Copy-on-Write)核心总结

1. 核心机制

  • 延迟复制 :值类型(如 ArrayString)在赋值时不立即复制内存,而是共享同一份数据。
  • 写入触发:仅当修改副本时,才真正创建新内存,确保原数据不受影响。

2. 实现原理

  • 内部引用 :值类型内部通过引用类型(如类)存储实际数据。
  • 引用计数检查 :写入前调用 isKnownUniquelyReferenced,检测数据引用是否唯一:
    • 唯一引用:直接修改原数据。
    • 多引用:创建新副本后再修改,避免共享数据意外变更。

3. 优势

  • 性能优化:减少不必要的数据复制,提升内存效率。
  • 值类型安全:保留值语义(独立修改),同时兼顾性能。

4. 适用场景

  • 高频赋值的大数据:如集合操作、字符串处理。
  • 标准库类型ArrayDictionarySetString 默认支持 COW。

5. 示例

swift 复制代码
var a = [1, 2, 3]  // 内部引用计数为 1
var b = a           // 引用计数 +1(共享数据)
b.append(4)         // 检测到多引用,复制新内存再修改(a 仍为 [1,2,3])

总结

COW 通过共享数据 + 写入时复制,平衡了值类型的安全性与性能,是 Swift 高效处理大数据的核心机制。

八、Swift 将集合类型设计为值类型的原因

1. 值类型的核心优势

  • 线程安全 :值类型在传递时通过复制确保数据独立性,避免多线程同时修改同一内存。
  • 无副作用:方法调用不会意外修改原始数据,代码行为更易推理。
  • 内存高效 :结合 写时复制(Copy-on-Write, COW),减少不必要的内存分配。

2. 具体设计动机

(1) 安全性优先
  • 避免隐式共享 :引用类型多个变量指向同一内存,修改一处会影响所有引用(如 NSMutableArray)。

  • 值类型赋值即复制 :每个变量持有独立数据,修改副本不影响原数据。

    swift 复制代码
    var a = [1, 2, 3]
    var b = a
    b.append(4)
    print(a) // [1, 2, 3](a 未被修改)
(2) 性能优化
  • 栈内存分配:值类型默认在栈上分配,操作高效(指针移动即可)。

  • 写时复制(COW) :延迟实际内存复制,仅在修改时创建新副本。

    swift 复制代码
    var largeArray = [Int](repeating: 0, count: 1000000)
    var copy = largeArray // 不立即复制内存(共享存储)
    copy[0] = 1          // 修改时触发复制(独立存储)
(3) 不可变性的真正保证
  • let 语义严格 :值类型声明为 let 后,内容完全不可变。

  • 引用类型的缺陷 :即使使用 let 修饰引用类型(如 NSArray),内部数据仍可能被修改。

    swift 复制代码
    let nsArray: NSArray = NSMutableArray()
    let swiftArray = [1, 2, 3]
    // nsArray 可被其他引用修改(不安全),swiftArray 完全不可变

3. 与引用类型的对比

特性 值类型(Array/String/Dictionary) 引用类型(NSArray/NSString)
内存分配 栈 + COW 优化堆内存 堆内存
线程安全 天然安全(独立内存) 需手动同步(如锁、GCD)
赋值行为 深拷贝(COW 延迟实际复制) 浅拷贝(共享内存)
不可变性 let 完全不可变 let 仅保证引用不变,内容可能被其他引用修改

4. 写时复制(COW)的实现原理

  1. 内部引用类型存储 :值类型内部使用类(如 _ContiguousArrayStorage)存储实际数据。

  2. 引用计数检测 :通过 isKnownUniquelyReferenced 检查数据是否被多引用。

  3. 按需复制 :修改数据时,若引用非唯一,则创建新副本再修改。

    swift 复制代码
    struct MyArray<T> {
        private var storage: Storage<T> // 内部引用类型
        mutating func append(_ element: T) {
            if !isKnownUniquelyReferenced(&storage) {
                storage = storage.copy()
            }
            storage.append(element)
        }
    }

5. 总结

  • 安全第一:值类型 + COW 解决了引用类型在多线程和共享数据中的安全隐患。
  • 性能平衡:栈内存和 COW 机制将复制开销降至最低。
  • 开发友好:严格的不可变性和可预测行为,减少代码副作用。

通过将 ArrayStringDictionary 设计为值类型,Swift 在内存效率、线程安全和代码可靠性之间取得了最佳平衡,同时借助 COW 技术避免了传统值类型的性能缺陷。

相关推荐
lilili啊啊啊7 小时前
IOS奔溃日志分析-克魔ios开发助手实战-以支付宝奔溃日志为例
ios
lichao8904279 小时前
JBDev - Theos下一代越狱开发工具
ios
二流小码农12 小时前
鸿蒙开发:使用Ellipse绘制椭圆
android·ios·harmonyos
二流小码农13 小时前
鸿蒙开发:使用Circle绘制圆形
android·ios·harmonyos
Macle_Chen13 小时前
XCode中使用MonkeyDev开发iOS版的Comand-line Tool的daemon程序
macos·ios·xcode·逆向·comand-line
二流小码农14 小时前
鸿蒙开发:使用Rect绘制矩形
android·ios·harmonyos
丁乾坤的博客15 小时前
iOS审核被拒:Missing privacy manifest 第三方库添加隐私声明文件
ios·manifest·第三方库隐私文件
Unlimitedz17 小时前
iOS GCD
macos·ios·cocoa
布多18 小时前
AutoreleasePool:iOS 内存管理乐章中的隐秘旋律
ios·源码阅读
YungFan18 小时前
SwiftUI-国际化
ios·swiftui·swift