【发布时间】:2021-10-23 09:33:00
【问题描述】:
我正在尝试在App 中放置一个StateObject actor,其初始值设定项为async,但我找不到这样做的方法。
假设我有这个演员:
actor Foo: ObservableObject {
init() async {
// ...
}
}
这会导致名义上的错误:
import SwiftUI
struct MyApp: App {
@StateObject
var foo = await Foo() // ???? 'async' call cannot occur in a property initializer
var body: some Scene {
// ...
}
}
这会导致类似的错误:
import SwiftUI
struct MyApp: App {
@StateObject
var foo: Foo
init() async {
_foo = .init(wrappedValue: await Foo()) // ???? 'async' call in a function that does not support concurrency
}
var body: some Scene {
// ...
}
}
即使这些也行不通:
import SwiftUI
struct MyApp: App {
@StateObject
var foo: Foo
init() async {
Task {
self._foo = .init(wrappedValue: await Foo()) // ???? Mutation of captured parameter 'self' in concurrently-executing code
}
}
var body: some Scene {
// ...
}
}
import SwiftUI
struct MyApp: App {
@StateObject
var foo: Foo
init() async {
Task { [self] in
self._foo = .init(wrappedValue: await Foo()) // ???? Cannot assign to property: 'self' is an immutable capture
}
}
var body: some Scene {
// ...
}
}
看来无论我做什么,我都不能让Foo 成为MyApp 的成员。我在这里想念什么?这当然是可能的。
我在使用 SwiftUI Views 时也遇到了同样的问题,所以任何适用于 Views 和 Apps 的建议都会非常棒!
【问题讨论】:
-
可能有一个技术原因,为什么不能使用异步函数来初始化属性包装器,但在语义层面:异步初始化 StateObject 时的预期行为是什么?显示加载指示器或空白屏幕不起作用 - 您甚至没有任何状态可以在呈现视图时告诉该视图。那么,这有意义吗?将 View 视为 同步(纯)函数是有意义的。
-
@loremipsum 否,因为那里的答案在我最后的 2 个 sn-ps 中被解决为不可用。不过,谢谢!
-
@CouchDeveloper 我希望应用程序初始化,同时在后台启动一些服务。我很想用一种方法来反映 UI 的启动,但老实说,如果我可以阻止主线程等待它,只在它们完成启动后才显示 UI,我会没事的;那会比我现在只是编译器错误的更好
-
@KyLeggiero 你应该再看看它。您的 sn-ps 显示与 Apple 的意图背道而驰。 1. SwiftUI 可以随时重新初始化
View,你的状态对象将是re initialized whenever SwiftUI decides,因为你是在init中设置它,而不是直接在包装器中,也可能导致泄漏。 2.根据您上面的评论,这也是错误的方法,因为async的重点是不阻塞主线程。
标签: swift async-await swiftui swift-concurrency