监控任务中 Actor 的已发布值时出现 Swift 6 构建错误

问题描述 投票:0回答:1

以下代码在 Xcode 中的 Swift 6 语言版本下构建时出现错误。这是架构中的问题还是有一个简单的解决方案?类型

Bool
Sendable
但它的发布者不是。

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

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
    }
}

请参阅此屏幕截图,了解我看到的 AVCam 示例代码中的实际错误(唯一的修改是将

@preconcurrency
放入
import AVFoundation
)。

Please refer to this screenshot for actual errors in AVCam sample code I see (without modifications)

ios swift combine swift-concurrency swift6
1个回答
0
投票

我不会直接使用

@Published
然后获取
values
,而是直接使用
AsyncStream
来传递值。如果流元素可发送,则
AsyncStream
是可发送的。

@propertyWrapper
struct Streamed<T: Sendable> {
    private var continuation: AsyncStream<T>.Continuation
    
    var projectedValue: AsyncStream<T>
    
    var wrappedValue: T {
        didSet {
            continuation.yield(wrappedValue)
        }
    }
    
    init(wrappedValue: T) {
        self.wrappedValue = wrappedValue
        (projectedValue, continuation) = AsyncStream.makeStream()
        continuation.yield(wrappedValue)
    }
}

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

然后在

observedValues

@MainActor
func observeValues() {
    Task {
        for await value in await writer.$isRecording {
            isRecording = value
        }
    }
}

请注意,为了确保

isRecording = value
的安全,
observeValues
或整个
Recorder
需要与全局参与者隔离。

© www.soinside.com 2019 - 2024. All rights reserved.