从任务中获取结果
Getting Result out of a Task
我有一个异步函数,它 returns App Store 查询的结果(查询成功或未显示在警报中)。我无法从任务中获取结果--无法在范围 中找到'result'。如果我移动 let gotTitle = result ? “成功”:“请求失败” 在任务中我看到警告“从未使用不可变值 'gotTitle' 的初始化”。
有关 Task 的 Apple 文档讨论了使用值或结果从任务中获取数据,但不清楚如何执行此操作。我还使用调试器单步调试了代码。它在任务中正确显示 result = true 和 gotTitle = Success。
struct TestAlert: View {
var gotTitle: String = ""
@State private var presentAlert = false
var body: some View {
VStack {
Button(action: {
Task {
let result = await restore()
print (result)
}
let gotTitle = result ? "Success" : "The Request Failed"
print(gotTitle)
}) {
Text("Restore Purchase")
}
}
.alert(gotTitle, isPresented: $presentAlert, actions: {
})
}
func restore() async -> Bool {
return ((try? await AppStore.sync()) != nil)
}
}
虽然不建议您像这样组合视图和业务逻辑(SwiftUI 更喜欢将其放在某种 ObservableObject
后面),但您可以像使用完成处理程序一样使用 Task
将完成的工作放入其中。
Task { @MainActor in // SwiftUI requires state is updated on the main queue.
// Perform async work.
// Update state.
}
你说:
I am having trouble getting the result out of the task
Cannot find 'result' in scope.
是的,如您的问题所述,result
是任务内部的局部变量,因此您不能在 Task
之外引用它(除非您保存它,或者标题字符串,在struct
).
的属性中
If I move let gotTitle = result ? "Success" : "The Request Failed" to within the task I see the warning "Initialization of immutable value 'gotTitle' was never used".
是的,您已将 gotTitle
定义为局部变量,恰好与同名的 属性 具有相同的名称。
所以,在我开始解决之前,让我们做一些观察,以便我们了解发生了什么。关键问题是 Task
里面有 await
异步运行 。 考虑:
var body: some View {
VStack {
Button(action: {
Task {
print(Date(), "started task")
let result = await restore()
let gotTitle = result ? "Success" : "The Request Failed" // a local variable; we'll fix this in the next example
print(Date(), "task finished", gotTitle)
}
print(Date(), "after task submitted")
}) {
Text("Restore Purchase")
}
}
.alert(gotTitle, isPresented: $presentAlert, actions: { })
}
请注意,我已将 let gotTitle
移到 块 Task
中。您不能在该代码块之外引用 result
。
无论如何,当您点击按钮时,您将在控制台中看到以下内容:
2022-04-18 00:38:03 +0000 after task submitted
2022-04-18 00:38:03 +0000 started task
2022-04-18 00:38:06 +0000 task finished Success
注意事件的顺序:
- “开始的任务”出现after“after task submitted”
- “任务完成”在“开始任务”几秒后出现
希望这能说明为什么引用 result
打印“任务提交后”的位置毫无意义。到那时你甚至还没有达到 result
的 declaration/assignment。
所以,这个故事的寓意是,如果你想在异步任务之后更新一些东西,它需要紧接在 await
行之后,在 Task
内(或者它的任何上下文)在)。如果将它放在 Task
之外,则意味着它不会等待异步 Task
完成。
那么,您将如何从 Task
块中访问结果。您可以将其保存到 ObservedProperty
(巧合的是,这有助于将业务逻辑与视图分开):
struct TestAlert: View {
@ObservedObject var restoreRequest = AppStoreRestoreRequest()
@State var isPresented = false
var body: some View {
VStack {
Button {
Task {
await restoreRequest.restore()
isPresented = true
}
} label: {
Text("Restore Purchase")
}
}
.alert(restoreRequest.state.title, isPresented: $isPresented, actions: { })
}
}
class AppStoreRestoreRequest: ObservableObject {
@Published var state: State = .notDetermined
func restore() async {
let result = (try? await AppStore.sync()) != nil
state = result ? .success : .failure
}
}
extension AppStoreRestoreRequest {
enum State {
case notDetermined
case success
case failure
}
}
extension AppStoreRestoreRequest.State {
var title: String {
switch self {
case .notDetermined: return "Not determined."
case .success: return "Success."
case .failure: return "The request failed."
}
}
}
因此,请求的性能(和当前状态)被拉出视图,请求的状态被捕获在 AppStoreRestoreRequest
.
这里是固定变体
struct TestAlert: View {
@State var gotTitle: String = "" // << state !!
@State private var presentAlert = false
var body: some View {
VStack {
Button(action: {
Task {
let result = await restore()
print (result)
await MainActor.run { // << update on Main !!
gotTitle = result ? "Success" : "The Request Failed"
print(gotTitle)
}
}
}) {
Text("Restore Purchase")
}
}
.alert(gotTitle, isPresented: $presentAlert, actions: {
})
}
func restore() async -> Bool {
return ((try? await AppStore.sync()) != nil)
}
}
我有一个异步函数,它 returns App Store 查询的结果(查询成功或未显示在警报中)。我无法从任务中获取结果--无法在范围 中找到'result'。如果我移动 let gotTitle = result ? “成功”:“请求失败” 在任务中我看到警告“从未使用不可变值 'gotTitle' 的初始化”。
有关 Task 的 Apple 文档讨论了使用值或结果从任务中获取数据,但不清楚如何执行此操作。我还使用调试器单步调试了代码。它在任务中正确显示 result = true 和 gotTitle = Success。
struct TestAlert: View {
var gotTitle: String = ""
@State private var presentAlert = false
var body: some View {
VStack {
Button(action: {
Task {
let result = await restore()
print (result)
}
let gotTitle = result ? "Success" : "The Request Failed"
print(gotTitle)
}) {
Text("Restore Purchase")
}
}
.alert(gotTitle, isPresented: $presentAlert, actions: {
})
}
func restore() async -> Bool {
return ((try? await AppStore.sync()) != nil)
}
}
虽然不建议您像这样组合视图和业务逻辑(SwiftUI 更喜欢将其放在某种 ObservableObject
后面),但您可以像使用完成处理程序一样使用 Task
将完成的工作放入其中。
Task { @MainActor in // SwiftUI requires state is updated on the main queue.
// Perform async work.
// Update state.
}
你说:
I am having trouble getting the result out of the task
Cannot find 'result' in scope.
是的,如您的问题所述,result
是任务内部的局部变量,因此您不能在 Task
之外引用它(除非您保存它,或者标题字符串,在struct
).
If I move let gotTitle = result ? "Success" : "The Request Failed" to within the task I see the warning "Initialization of immutable value 'gotTitle' was never used".
是的,您已将 gotTitle
定义为局部变量,恰好与同名的 属性 具有相同的名称。
所以,在我开始解决之前,让我们做一些观察,以便我们了解发生了什么。关键问题是 Task
里面有 await
异步运行 。 考虑:
var body: some View {
VStack {
Button(action: {
Task {
print(Date(), "started task")
let result = await restore()
let gotTitle = result ? "Success" : "The Request Failed" // a local variable; we'll fix this in the next example
print(Date(), "task finished", gotTitle)
}
print(Date(), "after task submitted")
}) {
Text("Restore Purchase")
}
}
.alert(gotTitle, isPresented: $presentAlert, actions: { })
}
请注意,我已将 let gotTitle
移到 块 Task
中。您不能在该代码块之外引用 result
。
无论如何,当您点击按钮时,您将在控制台中看到以下内容:
2022-04-18 00:38:03 +0000 after task submitted
2022-04-18 00:38:03 +0000 started task
2022-04-18 00:38:06 +0000 task finished Success
注意事件的顺序:
- “开始的任务”出现after“after task submitted”
- “任务完成”在“开始任务”几秒后出现
希望这能说明为什么引用 result
打印“任务提交后”的位置毫无意义。到那时你甚至还没有达到 result
的 declaration/assignment。
所以,这个故事的寓意是,如果你想在异步任务之后更新一些东西,它需要紧接在 await
行之后,在 Task
内(或者它的任何上下文)在)。如果将它放在 Task
之外,则意味着它不会等待异步 Task
完成。
那么,您将如何从 Task
块中访问结果。您可以将其保存到 ObservedProperty
(巧合的是,这有助于将业务逻辑与视图分开):
struct TestAlert: View {
@ObservedObject var restoreRequest = AppStoreRestoreRequest()
@State var isPresented = false
var body: some View {
VStack {
Button {
Task {
await restoreRequest.restore()
isPresented = true
}
} label: {
Text("Restore Purchase")
}
}
.alert(restoreRequest.state.title, isPresented: $isPresented, actions: { })
}
}
class AppStoreRestoreRequest: ObservableObject {
@Published var state: State = .notDetermined
func restore() async {
let result = (try? await AppStore.sync()) != nil
state = result ? .success : .failure
}
}
extension AppStoreRestoreRequest {
enum State {
case notDetermined
case success
case failure
}
}
extension AppStoreRestoreRequest.State {
var title: String {
switch self {
case .notDetermined: return "Not determined."
case .success: return "Success."
case .failure: return "The request failed."
}
}
}
因此,请求的性能(和当前状态)被拉出视图,请求的状态被捕获在 AppStoreRestoreRequest
.
这里是固定变体
struct TestAlert: View {
@State var gotTitle: String = "" // << state !!
@State private var presentAlert = false
var body: some View {
VStack {
Button(action: {
Task {
let result = await restore()
print (result)
await MainActor.run { // << update on Main !!
gotTitle = result ? "Success" : "The Request Failed"
print(gotTitle)
}
}
}) {
Text("Restore Purchase")
}
}
.alert(gotTitle, isPresented: $presentAlert, actions: {
})
}
func restore() async -> Bool {
return ((try? await AppStore.sync()) != nil)
}
}