gpt4 book ai didi

Using @MainActor to replace await keyword(使用@MainActor替换AWait关键字)

转载 作者:bug小助手 更新时间:2023-10-28 21:24:47 25 4
gpt4 key购买 nike



I have a function that runs in the main view model to listen for Auth Status changes and perform actions.

我有一个在主视图模型中运行的函数,用于监听Auth状态更改并执行操作。


class MainViewModel: ViewModel {

private var cancellableSet: Set<AnyCancellable> = []

override init() {
super.init()

// Listen for auth status changes
Task(priority: .high) {
await listenForAuthStatusChanges()
}
}


// When auth status changes to true setup service
@MainActor
private func listenForAuthStatusChanges() async {
SessionManager.shared.$isAuthenticated
.receive(on: DispatchQueue.main)
.sink { isAuthenticated in
if isAuthenticated == true {
self.setupService()
}
}
.store(in: &cancellableSet)
}
.../



SessionManager.isAuthenticated is a Published property

SessionManager.isAuthenticated是已发布的属性


@Published private(set) var isAuthenticated: Bool? = nil

If I remove @MainActor then I get an error Expression is 'async' but is not marked with 'await' and I have to add await before SessionManager.shared.$isAuthenticated to satisfy the error.

如果我删除@MainActor,则会得到一个错误表达式‘async’,但没有标记为‘aWait’,并且我必须在SessionManager.Shared之前添加aWait以满足该错误。



  1. SessionManager.shared.$isAuthenticated is not an async function, it's a simple published property. Why would you have to await a published property?



  2. What does @MainActor have to do with async/await and why does it's use negate the need for the await?




    private func listenForAuthStatusChanges() async {
await SessionManager.shared.$isAuthenticated
.receive(on: DispatchQueue.main)
.sink { isAuthenticated in
if isAuthenticated == true {
self.setupService()
}
}
.store(in: &cancellableSet)
}


更多回答

Why is session manager on the MainActor? Mixing GCD and actors is usually a source of issues. Have you turned on “strict concurrency”? Does this pass swift 6 muster?

为什么会话管理器位于MainActor上?将GCD和演员混合在一起通常是一个问题的来源。您是否启用了“严格并发”?这是不是很快就通过了?

优秀答案推荐

I think I figured it out. SessionManager is a @MainActor which inherently makes the calling of all its methods and properties async, when called from a background context. By marking @MainActor on the caller, then both caller and callee are on the main thread.

我想我想通了。SessionManager是一个@MainActor,当从后台上下文调用时,它固有地使其所有方法和属性的调用同步。通过在调用方上标记@MainActor,则调用方和被调用方都在主线程上。




SessionManager.shared.$isAuthenticated is not an async function, it's a simple published property. Why would you have to await a published property?



It's not what because of what SessionManager is, it's because of what the context is. listenForAuthStatusChanges is an async method. Therefore the compiler takes over and enforces thread-safety. The await makes sure that two possibly conflicting things do not take place at the same time. You cannot talk to one actor from another without saying await.

这不是因为SessionManager是什么,而是因为上下文是什么。ListenForAuthStatusChanges是一个异步方法。因此,编译器接管并实施线程安全。等待确保两件可能相互冲突的事情不会同时发生。你不能不打招呼就和另一位演员交谈。



What does @MainActor have to do with async/await



It has everything to do with async/await. It is part of async/await. Or rather, they are both part of structured concurrency.

这与异步/等待有很大关系。它是异步/等待的一部分。或者,它们都是结构化并发的一部分。



why does it's use negate the need for the await



Because it guarantees that your code and the session manager code run on the same actor — namely the main actor. Now you are not talking to one actor from another, so await is not needed.

因为它保证了您的代码和会话管理器代码在同一个参与者上运行--即主参与者。现在,您不是在与一个演员与另一个演员交谈,因此不需要等待。


更多回答

Close, but do not say "thread". Swift structured concurrency is about actors. It's okay to say "context", though; in fact, that's a very useful term when understanding structured concurrency. "SessionManager is a @MainActor which inherently makes the calling of all its methods and properties async" You're saying that very badly — its methods and properties do not magically become async — but I think you mean the right thing. As I explain in my answer, it's a matter of whether you are talking between different actors. You can think of those as thread contexts (but don't).

接近,但不要说“线”。SWIFT结构化并发与参与者有关。不过,可以说“上下文”;事实上,在理解结构化并发时,这是一个非常有用的术语。“SessionManager是一个@MainActor,它固有地使其所有方法和属性的调用同步。”你说得很糟糕--它的方法和属性不会神奇地变得不同步--但我认为你说的是对的。正如我在回答中解释的那样,这是一个你是否在不同演员之间交谈的问题。您可以将这些视为线程上下文(但不能)。

Yet annoyingly, its parent context isn't guaranteed to be applied in a Combine sink, just like using receive(on: DispatchQueue.main) doesn't apply MainActor context to any code inside the sink. So if you change the Combine sink to receive on a different queue, the code inside the sink will still assume the context of the parent actor (e.g. MainActor in this example)

然而,令人恼火的是,它的父上下文不能保证在组合接收器中应用,就像使用接收(on:DispatchQueue.main)不会将MainActor上下文应用于接收器中的任何代码一样。因此,如果您将合并接收器更改为在不同队列上接收,接收器中的代码仍将采用父参与者的上下文(例如,本例中的MainActor)

Well you shouldn't be combining (sorry) Combine and async/await. But that wasn't the question that was posed.

那么,您不应该组合(抱歉)组合和异步/等待。但这不是提出的问题。

eh, it's perfectly fine to combine the two. async/await doesn't have a pub/sub pattern, and it's perfectly plausible to need to do a async operation (like a network call) in response to a subscription (like storing remotely how much of a podcast you listened to in response to a AVPlayer currentTime subscriber)

呃,把这两者结合起来是非常好的。异步/等待没有发布/订阅模式,完全有可能需要执行异步操作(比如网络呼叫)来响应订阅(比如远程存储你收听了多少播客以响应AVPlayerCurrentTime订阅者)

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com