SwiftUI中如何向视图传递可选函数作为参数?
SwiftUI 实现支持可选自定义动作的 YesOrNoView
你不需要用泛型来实现这个需求,直接给视图添加一个可选的逃逸闭包作为自定义动作参数即可,这是SwiftUI处理这类场景的常规做法。
正确的视图实现
struct YesOrNoView: View { @Binding var questionAnswer: Bool @Binding var questionsAnswered: Int // 可选自定义动作,默认值为nil,@escaping标记闭包会在视图生命周期外执行 var customAction: (() -> Void)? var body: some View { HStack(spacing: 20) { Button("是") { questionAnswer = true questionsAnswered += 1 // 仅当存在自定义动作时执行 customAction?() } .buttonStyle(.borderedProminent) Button("否") { questionAnswer = false questionsAnswered += 1 customAction?() } .buttonStyle(.bordered) } } }
为什么你之前的泛型写法会出错
你尝试的<Content: Action>写法不成立,因为Swift标准库和SwiftUI里并没有名为Action的内置协议,这是混淆了UIKit的概念。而无约束的泛型<Content>会让Swift无法推断Content的具体类型——你并没有在视图中使用这个泛型参数,自然会报错。
使用示例
- 普通题目(无需自定义动作):直接传入绑定参数即可
// 假设你在父视图中定义了对应的绑定变量 @State private var currentAnswer = false @State private var answeredCount = 0 // 调用YesOrNoView YesOrNoView(questionAnswer: $currentAnswer, questionsAnswered: $answeredCount)
- 最后一题(需要自定义跳转逻辑):传入闭包实现自定义动作
// 假设父视图有导航路径绑定 @State private var navPath = NavigationPath() // 调用时传入自定义跳转逻辑 YesOrNoView(questionAnswer: $finalAnswer, questionsAnswered: $answeredCount) { navPath.append(ResultView()) }
进阶:根据回答结果执行不同逻辑
如果你的自定义动作需要依赖用户选择的“是/否”结果,可以把闭包改成接受Bool参数:
// 修改视图的自定义动作参数 var customAction: ((Bool) -> Void)? // 按钮中调用时传入当前回答 Button("是") { questionAnswer = true questionsAnswered += 1 customAction?(questionAnswer) } Button("否") { questionAnswer = false questionsAnswered += 1 customAction?(questionAnswer) }
使用时可以根据回答分支处理:
YesOrNoView(questionAnswer: $finalAnswer, questionsAnswered: $answeredCount) { answer in if answer { navPath.append(SuccessView()) } else { navPath.append(FailureView()) } }
内容的提问来源于stack exchange,提问作者SwiftlySlow
相关产品推荐
相关产品推荐

