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

Swift 6设置下Task闭包传递sending参数引发并发数据竞争错误

Swift 6中Task闭包数据竞争警告的解决办法

问题原因

Swift 6对并发安全的检查更加严格,当你在非actor类型的类(比如示例中的Recorder)里创建普通Task时,闭包会隐式捕获当前上下文的发送者(即Recorder实例)。由于Recorder不是线程安全的类型,闭包的并发执行可能和当前线程对Recorder属性的操作产生数据竞争,因此编译器抛出该警告。

解决方法

方法1:使用Task.detached创建独立任务

Task.detached不会继承当前任务的上下文,也不会隐式捕获发送者。同时显式捕获需要的属性(比如writer),避免捕获整个Recorder实例,进一步降低风险:

import Foundation

final class Recorder {
    
    var writer = Writer()
    
    func startRecording() {
        Task.detached { [writer] in
            await writer.startRecording()
            print("started recording")
        }
    }
    
    func stopRecording() {
        Task.detached { [writer] in
            await writer.stopRecording()
            print("stopped recording")
        }
    }
}

actor Writer {
    var isRecording = false
    
    func startRecording() {
        isRecording = true
    }
    
    func stopRecording() {
        isRecording = false
    }
}

方法2:将Recorder改为actor类型

将Recorder声明为actor后,它的所有属性访问和方法调用都会在串行执行上下文中进行,内部创建的Task会继承该上下文,从根本上消除数据竞争的可能:

import Foundation

final actor Recorder {
    
    var writer = Writer()
    
    func startRecording() {
        Task {
            await writer.startRecording()
            print("started recording")
        }
    }
    
    func stopRecording() {
        Task {
            await writer.stopRecording()
            print("stopped recording")
        }
    }
}

actor Writer {
    var isRecording = false
    
    func startRecording() {
        isRecording = true
    }
    
    func stopRecording() {
        isRecording = false
    }
}

方法3:显式控制闭包捕获范围

如果不想修改Recorder的类型,也可以在普通Task中使用弱引用或显式捕获需要的属性,避免隐式捕获整个Recorder实例:

func startRecording() {
    Task { [weak self] in
        guard let writer = self?.writer else { return }
        await writer.startRecording()
        print("started recording")
    }
}

func stopRecording() {
    Task { [weak self] in
        guard let writer = self?.writer else { return }
        await writer.stopRecording()
        print("stopped recording")
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 03:55:02