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

Swift 6下监控Actor中Published值的编译错误排查与解决问询

Swift 6下Published<Bool>.Publisher跨Actor边界报错的修复方案

在Swift 6编译环境下,上述代码出现以下报错:

Non-sendable type 'Published.Publisher' in implicitly asynchronous access to actor-isolated property '$isRecording' cannot cross actor boundary

问题核心是:虽然Bool是Sendable类型,但Published<Bool>.Publisher本身并未遵循Sendable协议,在Swift 6的严格并发安全检查下,无法跨Actor边界传递Actor隔离的$isRecording属性。类似问题也出现在添加@preconcurrency import AVFoundation后的AVCam示例代码中。

代码示例

import Foundation

final class Recorder {
    
    var writer = Writer()
    var isRecording = false
    
    func startRecording() {
        Task { [writer] in
            await writer.startRecording()
            print("started recording")
        }
    }
    
    func stopRecording() {
        Task { [writer] in
            await writer.stopRecording()
            print("stopped recording")
        }
    }
    
    func observeValues() {
        
        Task {
            for await value in await writer.$isRecording.values {
                isRecording = value
            }
        }
    }
}

actor Writer {
    @Published private(set) public var isRecording = false
    
    func startRecording() {
        isRecording = true
    }
    
    func stopRecording() {
        isRecording = false
    }
}

修复方案

这并非架构问题,有两种简易修复方案:

方案1:用AsyncStream封装状态流(推荐,符合Swift并发模型)

在Writer Actor内部添加一个返回异步序列的方法,避免直接暴露非Sendable的Published.Publisher:

actor Writer {
    @Published private(set) public var isRecording = false
    
    func startRecording() {
        isRecording = true
    }
    
    func stopRecording() {
        isRecording = false
    }
    
    // 新增:封装状态更新为异步序列
    func recordingStatusUpdates() -> AsyncStream<Bool> {
        AsyncStream { continuation in
            let cancellable = $isRecording.sink { value in
                continuation.yield(value)
            }
            continuation.onTermination = { _ in
                cancellable.cancel()
            }
        }
    }
}

修改Recorder的observeValues方法,直接调用新方法获取异步序列:

func observeValues() {
    Task {
        for await value in writer.recordingStatusUpdates() {
            isRecording = value
        }
    }
}

方案2:给Published.Publisher添加@unchecked Sendable标记(临时兼容,不推荐)

如果需要保留原有Published的使用方式,可以通过扩展让Published<Bool>.Publisher遵循@unchecked Sendable,但这种方式会绕过Swift的并发安全检查,仅适合临时场景:

extension Published.Publisher: @unchecked Sendable where Output: Sendable, Failure == Never {}

内容的提问来源于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 04:22:24