You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI传递带泛型参数的函数时ChildView的参数如何定义

报错原因

你原来的两种写法无法编译的核心原因是:Swift不允许直接在结构体的属性上声明泛型参数,泛型参数需要定义在结构体本身的声明层级,或者通过类型擦除抹掉具体类型约束。

方案1:给ChildView添加泛型参数(推荐,编译时类型安全)

如果单个ChildView实例只会返回固定一种类型的GeneralAnswer(比如这个ChildView是数字输入页就只传Int,文本输入页就只传String),直接把泛型参数声明在ChildView结构体上即可:

// 正确的ChildView定义
struct ChildView<T>: View {
    var okClicked: (GeneralAnswer<T>) -> Void
    
    var body: some View {
        // 内部调用示例
        Button("提交") {
            // 传入对应类型的参数即可,比如Int类型
            okClicked(GeneralAnswer(value: 2024))
            // 如果是String类型就写 okClicked(GeneralAnswer(value: "测试结果"))
        }
    }
}

ParentView的原有代码不需要做任何修改,Swift会自动根据使用场景推导T的具体类型。

方案2:类型擦除支持多类型返回

如果同一个ChildView实例需要返回多种不同类型的GeneralAnswer,可以用Swift 5.7+提供的any关键字做类型擦除:

  1. 先给GeneralAnswer添加公共协议:
protocol GeneralAnswerProtocol {}
extension GeneralAnswer: GeneralAnswerProtocol {}
  1. 定义ChildView:
struct ChildView: View {
    var okClicked: (any GeneralAnswerProtocol) -> Void
    
    var body: some View {
        VStack {
            Button("提交数字") {
                okClicked(GeneralAnswer(value: 100))
            }
            Button("提交文本") {
                okClicked(GeneralAnswer(value: "提交的文本内容"))
            }
        }
    }
}
  1. 对应修改ParentView的okClicked实现:
struct ParentView: View {
    func okClicked(userAnswer: any GeneralAnswerProtocol) {
        // 内部按需做类型判断即可
        if let intRes = userAnswer as? GeneralAnswer<Int> {
            print("收到数字:\(intRes.value)")
        } else if let stringRes = userAnswer as? GeneralAnswer<String> {
            print("收到文本:\(stringRes.value)")
        }
    }

    var body: some View {
        ChildView(okClicked: okClicked)
    }
}

内容的提问来源于stack exchange,提问作者DevB2F

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 23:06:08