You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift 5.10:非隔离deinit访问非Sendable类型警告的解决办法

解决Swift并发警告:非Sendable类型在deinit中访问的问题

问题原因

开启完整严格并发检查后,Swift会强制要求跨隔离上下文访问的类型符合Sendable协议,以此保障线程安全。你的AuthController未实现Sendable,而deinit属于非隔离上下文,直接访问非Sendable类型的属性就会触发警告,Swift 6中这会升级为错误。

以下是几种可行的解决方法:


方法1:让AuthController符合Sendable协议

如果AuthController的实现本身是线程安全的(比如没有共享可变状态,或者所有状态访问都做了线程同步),直接让它遵循Sendable协议即可:

class AuthController: Sendable {
    func signInAnonymouslyIfNecessary() {
        
    }
}

如果AuthController内部包含非Sendable的属性,但你能手动保证这些属性的线程安全访问,可以使用@unchecked Sendable(需谨慎,仅当你确认线程安全时使用):

class AuthController: @unchecked Sendable {
    // 假设这个属性的访问已经做了线程同步
    private var mutableState: String = ""
    
    func signInAnonymouslyIfNecessary() {
        
    }
}

方法2:用Task包裹deinit中的调用

如果不想修改AuthController的协议一致性,可以将调用放到异步任务中,让访问在隔离上下文执行:

deinit {
    Task {
        authController.signInAnonymouslyIfNecessary()
    }
}

注:Task会异步执行代码,但由于authController被AuthFormNavC强持有,deinit执行时authController尚未释放,因此调用是安全的。如果你的方法需要同步执行,这种方式不适用。


方法3:将导航控制器标记为@MainActor

如果signInAnonymouslyIfNecessary()必须在主线程执行,且AuthController的操作本身是主线程安全的,可以让AuthFormNavC归属于MainActor,这样deinit会在主线程隔离上下文执行,访问authController就不会有警告:

@MainActor
class AuthFormNavC: UINavigationController {
    let authController: AuthController

    init(authController: AuthController) {
        self.authController = authController
        super.init(rootViewController: ConsentVC())
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    deinit {
        authController.signInAnonymouslyIfNecessary()
    }
}

如果AuthController本身也是@MainActor修饰的,这种方式的线程安全性会更有保障。


内容的提问来源于stack exchange,提问作者Filippo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 14:22:07