SwiftUI报错:buildExpression要求ValueWidget遵循AccessibilityRotorContent
Static method 'buildExpression' requires that 'ValueWidget' conform to 'AccessibilityRotorContent' 问题详情
报错信息:Static method 'buildExpression' requires that 'ValueWidget' conform to 'AccessibilityRotorContent'
使用环境:macOS Sonoma + Xcode 15.0
相关代码
ContentView.swift
struct ContentView: View { var body: some View { let data = (1...100).map { "Item \($0)" } let columns = [ GridItem(.adaptive(minimum: 80)) ] let v: Double = -10.0 ScrollView { LazyVGrid(columns: columns, spacing: 20) { ForEach(data, id: \.self) { item in ValueWidget(name: item, value: v) v = v + 0.5; } } .padding(.horizontal) } .frame(maxHeight: 300) } } /* #Preview { ContentView() }*/ struct ValueWidget_Previews: PreviewProvider { static var previews: some View { ValueWidget(name: "Hello", value: 42.0) } }
ValueWidget.swift
import SwiftUI struct ValueWidget: View { var name: String var value: Double var body: some View { VStack { Text(String(format: "%.1f", value)) .font(.system(size: 40)) .fontWeight(.bold) .foregroundColor(Color.blue) Text(name) } .padding() .background() .cornerRadius(10) .fixedSize() .frame(width: 120.0, height: 70.0) .padding() .accessibilityLabel(Text("\(name), Wert: \(value)")) } } #Preview { ValueWidget(name: "Hello", value: 42.0) }
已尝试方法:替换预览代码为ValueWidget_Previews,但问题未解决。
问题原因
Xcode给出的报错信息具有误导性,实际问题并非ValueWidget需要遵循AccessibilityRotorContent协议,而是在SwiftUI的View构建闭包(body)中直接修改了用let声明的不可变变量v。
SwiftUI的body要求是纯函数,不能包含副作用(比如修改外部变量),这种非法操作导致编译器抛出错误提示,但错误信息指向了无关的协议一致性问题。
解决方法
通过循环索引计算value,避免修改变量,具体修改步骤如下:
修改
ForEach的遍历方式,同时获取索引和元素:
将原来的ForEach(data, id: \.self) { item in改为ForEach(Array(data.enumerated()), id: \.element) { index, item in根据索引计算对应的
value值:
将ValueWidget(name: item, value: v)改为ValueWidget(name: item, value: -10.0 + Double(index) * 0.5)删除原来的
let v: Double = -10.0和循环内的v = v + 0.5;语句
修改后的ContentView代码:
struct ContentView: View { var body: some View { let data = (1...100).map { "Item \($0)" } let columns = [ GridItem(.adaptive(minimum: 80)) ] ScrollView { LazyVGrid(columns: columns, spacing: 20) { ForEach(Array(data.enumerated()), id: \.element) { index, item in ValueWidget(name: item, value: -10.0 + Double(index) * 0.5) } } .padding(.horizontal) } .frame(maxHeight: 300) } } #Preview { ContentView() }
这样修改后,既符合SwiftUI的纯函数要求,又能实现每个ValueWidget的value从-10.0开始每次递增0.5的需求,同时解决了报错问题。
内容的提问来源于stack exchange,提问作者Lc___

