我try 了代码所在的POST https://www.swiftbysundell.com/articles/building-an-async-swiftui-button/,但在 struct 中添加了优先级常量. 如果我使用的优先级是.utility,但如果我使用的是.userInitiated,则按钮正在做它应该做的事情(仅在Hibernate 时间结束时显示ProgressView,然后仅在操作完成之前显示ProgressView).为什么会这样呢?在触发showProgressView=TRUE语句之前,.cancel()函数不应该取消这两个操作吗?
当点击按钮".userInitiated"时,控制台输出为:
- 任务已取消
- 已创建任务
视频:https://imgur.com/a/SQJu1AM
struct ContentView: View{
@State var count = 0
@State var showProg = false
func heavyTask() async throws ->Int{
var k = count
for _ in 0..<5_000_000{
k += 1
}
return k
}
var body: some View{
VStack{
AsyncButton(action: {try? await count = heavyTask()},actionOptions: [.showProgressView], label: {
Text(".utility")
}, priority: .utility)
AsyncButton(action: {try? await count = heavyTask()},actionOptions: [.showProgressView], label: {
Text(".userInitiated")
}, priority: .userInitiated)
Text("result: \(count)")
}
}
}
struct AsyncButton<Label: View>: View {
var action: () async -> Void
var actionOptions = Set(ActionOption.allCases)
@ViewBuilder var label: () -> Label
let priority: TaskPriority
@State private var isDisabled = false
@State private var showProgressView = false
var body: some View {
Button(
action: {
if actionOptions.contains(.disableButton) {
isDisabled = true
}
Task {
var progressViewTask: Task<Void, Error>?
if actionOptions.contains(.showProgressView) {
progressViewTask = Task(priority: priority) {
try await Task.sleep(nanoseconds: 900_000_000)
showProgressView = true
print("已创建任务")
}
}
await action()
progressViewTask?.cancel()
print("任务已取消")
isDisabled = false
showProgressView = false
}
},
label: {
ZStack {
label().opacity(showProgressView ? 0 : 1)
if showProgressView {
ProgressView()
}
}
}
)
.disabled(isDisabled)
}
}
extension AsyncButton {
enum ActionOption: CaseIterable {
case disableButton
case showProgressView
}
}