如何将Uicontrol发行商迁移到Swift 6,而无需并发警告

问题描述 投票:0回答:1
I根据以下代码创建了UIControl的发布者:

原始代码要素 source:中间文章

,但是,当我尝试通过严格的并发检查迁移到Swift 6时,我遇到了以下与上下文相关的警告:

to-call to-call to to to to aiddtarget(_:action::)'在同步的非分离上下文中

要解决此问题,我进行了几次更改,以在代码的某些部分(标记为✅更改)中使用MainActor。这是更新的代码:

protocol UIControlPublishable: UIControl {} extension UIControlPublishable { func publisher(for event: UIControl.Event) -> UIControl.InteractionPublisher<Self> { return InteractionPublisher(control: self, event: event) } } extension UIControl: UIControlPublishable { @MainActor // ✅ Changed class InteractionSubscription<S: Subscriber, C: UIControl>: Subscription where S.Input == C { private let subscriber: S? private weak var control: C? private let event: UIControl.Event init(subscriber: S, control: C?, event: UIControl.Event) { self.subscriber = subscriber self.control = control self.event = event self.control?.addTarget(self, action: #selector(handleEvent), for: event) } @objc func handleEvent(_ sender: UIControl) { guard let control = self.control else { return } _ = self.subscriber?.receive(control) } nonisolated func request(_ demand: Subscribers.Demand) {} nonisolated func cancel() { Task { @MainActor in // ✅ Changed self.control?.removeTarget(self, action: #selector(handleEvent), for: self.event) self.control = nil } } } enum InteractionPublisherError: Error { case objectFoundNil } struct InteractionPublisher<C: UIControl>: Publisher { typealias Output = C typealias Failure = InteractionPublisherError private weak var control: C? private let event: UIControl.Event init(control: C, event: UIControl.Event) { self.control = control self.event = event } func receive<S>(subscriber: S) where S : Subscriber, InteractionPublisherError == S.Failure, C == S.Input { Task { @MainActor in // ✅ Changed // ❌ Task or actor isolated value cannot be sent; this is an error in the Swift 6 language mode guard let control = control else { subscriber.receive(completion: .failure(.objectFoundNil)) return } let subscription = InteractionSubscription( subscriber: subscriber, control: control, event: event ) subscriber.receive(subscription: subscription) } } } }

此更新后,在尝试在Mainactor上下文中访问接收函数内的订户时,我遇到了以下警告:

func receive<S>(subscriber: S) where S : Subscriber, InteractionPublisherError == S.Failure, C == S.Input { Task { @MainActor in // ❌ Task or actor isolated value cannot be sent; this is an error in the Swift 6 language mode guard let control = control else { subscriber.receive(completion: .failure(.objectFoundNil)) return } let subscription = InteractionSubscription( subscriber: subscriber, control: control, event: event ) subscriber.receive(subscription: subscription) } }

即可简化任务内部的代码以仅使用订阅者在同一问题中结果:
        func receive<S>(subscriber: S) where S : Subscriber, InteractionPublisherError == S.Failure, C == S.Input {
            Task { @MainActor in
                let temp = subscriber
            }
        }

我试图用任务捕获订户,但问题仍然存在。
我如何在不遇到此问题的情况下将此代码迁移到Swift 6?
    

commbine本身并没有真正迁移到Swift 6,由于它如何处理并发,我无法想象它永远不会迁移到Swift 6。组合订户可以在他们想要使用

{ @MainActor [subscriber] in }
subscribe(on:)

的任何队列上请求和接收值,因此闭合

receive(on:)
接受应该是

sink

,但不是。预计,如果您

@Sendable
swift concurrency uikit swift6 mainactor
1个回答
0
投票
receive(on: DispatchQueue.global())

错误基本上说您不应该将
sink
发送给主要参与者 - 它应该留在原处,因为用户可以决定与
subscriber
.
由于该出版商仅在主要演员上使用有意义,因此您不妨使用
subscribe(on:)
符合:
@preconcurrency

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.