SwiftUI报Type '()' cannot conform to 'View' 遍历求和问题排查
问题原因
触发Type '()' cannot conform to 'View'报错是API误用导致的,代码中一共存在三处问题:
- 核心错误:
ForEach是SwiftUI专门用来生成视图的组件,仅能在View的body闭包内使用,作用是遍历数据集合并返回对应的视图序列,不能用来实现普通的数组遍历逻辑。你在普通类的计算方法里调用ForEach,系统会判定你需要返回遵循View协议的内容,但你实际写的是累加逻辑,返回类型完全不匹配,直接触发报错。 - 用法错误:
@EnvironmentObject是SwiftUI视图专用的属性包装器,只能在遵守View协议的结构体里使用,不能在普通的ObservableObject类中通过这个包装器注入依赖,运行时拿不到对应的实例。 - 逻辑错误:你把计算结果存在类的
@Published var sum属性中,每次调用计算方法不重置初始值的话,会重复累加数值,最终计算结果错误。
修正方案
普通数组遍历做数值计算直接用Swift基础语法的循环即可,不需要调用SwiftUI的视图组件。如果要在这个类里持有ListViewModel的引用,通过初始化方法传入即可,修正后的代码如下:
import Foundation import SwiftUI // Swift类名遵循大驼峰命名规范 class Sums: ObservableObject{ @Published var sum: Double = 0 // 改为普通持有属性,通过初始化传入实例 private let listViewModel: ListViewModel init(listViewModel: ListViewModel) { self.listViewModel = listViewModel } func calculateTotal() -> Double{ // 每次计算前重置总和,避免重复累加 sum = 0 // 用基础for循环遍历数组做计算 for item in listViewModel.items { sum += item.test } return sum } }
如果ListViewModel本身就是全局注入的环境对象,不需要单独写这个求和类,直接在需要展示总和的View里通过@EnvironmentObject拿到实例,用计算属性直接求和即可,代码更简洁:
struct TotalProgressView: View { @EnvironmentObject var listViewModel: ListViewModel // 用reduce高阶函数直接求和,不需要额外维护存储属性 private var totalSum: Double { listViewModel.items.reduce(0) { $0 + $1.test } } var body: some View { Text("总进度:\(totalSum)") } }
提示:简单的数组聚合计算优先用
reduce这类高阶函数,不需要手动维护累加变量,也不会出现重复累加的逻辑问题。
内容的提问来源于stack exchange,提问作者Daniel Munteanu
相关产品推荐
相关产品推荐

