初级Swift开发者常见错误:高级篇

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

初级Swift开发者常见错误:高级篇



当你从编写简单的SwiftUI界面转向构建具有自定义架构的复杂多线程应用时,潜在陷阱的数量会急剧增加。许多开发者在掌握了Swift的基本语法后,便认为自己已准备好投入生产环境,但却会犯下导致内存泄漏、运行不稳定以及难以追踪的bug等严重错误。在本文中,我们将分析中级开发者最常遇到的四类错误。



1. 闭包中的内存泄漏:不仅仅是 [weak self]



最常见的错误是在不理解何时真正需要的情况下使用 [weak self]。许多开发者在所有闭包中都加上 weak self,这会导致对象过早被销毁。或者,他们会在不明显的地方忘记处理强引用循环。



典型错误: 在闭包内部创建对持有该闭包的对象的强引用。



class NetworkManager {    var onCompletion: (() -> Void)?        func fetchData() {        // 错误:闭包强捕获了 self        onCompletion = {            self.updateUI()        }    }        func updateUI() {        print("UI 已更新")    }}


正确解决方案: 根据对象的生命周期使用 [weak self] 或 [unowned self]。



class NetworkManager {    var onCompletion: (() -> Void)?        func fetchData() {        onCompletion = { [weak self] in            guard let self = self else { return }            self.updateUI()        }    }        func updateUI() {        print("UI 已更新")    }}


高级细节: 谨慎使用 [unowned self]。如果对象被释放而闭包被调用,应用将会崩溃。只有在100%确定对象生命周期长于闭包时,才使用 unowned。



2. async/await 和 Actor 的不当使用



随着 Swift 5.5 中 Structured Concurrency 的出现,许多开发者开始积极使用 async/await,但忘记了 MainActor 和 Sendable。这会导致竞态条件以及在后台线程更新UI的问题。



典型错误: 调用一个本应在主线程执行的异步函数,但没有显式标记 @MainActor。



class ViewModel: ObservableObject {    @Published var data: [String] = []        // 错误:函数未标记 @MainActor    func loadData() async {        let result = await fetchFromNetwork()        // 这可能在后台线程执行!        self.data = result    }        func fetchFromNetwork() async -> [String] {        try? await Task.sleep(nanoseconds: 1_000_000_000)        return ["Item1", "Item2"]    }}


正确解决方案: 为更新UI的函数使用 @MainActor。



class ViewModel: ObservableObject {    @Published var data: [String] = []        @MainActor // 现在保证在主线程执行    func loadData() async {        let result = await fetchFromNetwork()        self.data = result    }        func fetchFromNetwork() async -> [String] {        try? await Task.sleep(nanoseconds: 1_000_000_000)        return ["Item1", "Item2"]    }}


高级细节: 不要忘记 nonisolated 和 actor。如果你使用 actor,所有公开方法默认是异步的。如果你没有仔细考虑隔离性,这可能会导致意外的延迟。



3. 竞态条件在

博客

书籍推荐