SwiftUI中创建带@Binding参数的结构体及解决类型转换错误
解决SwiftUI中"Cannot convert value of type 'Bool' to expected argument type 'Binding'"错误
错误原因
你当前的写法存在两个核心问题:
- 直接给
@Binding参数传普通Bool值:HabitEggButton的display是@Binding类型,它需要绑定到一个可变的状态源(比如@State/@ObservedObject属性),而非直接传入true这类常量值。 - 将View实例存入
@State数组:SwiftUI的View是描述界面的结构体,应该由数据驱动渲染,不适合直接把View实例存储到状态数组中。
修复方案:数据与视图分离
正确的思路是把状态抽成独立的数据模型,让视图依赖数据渲染,具体步骤如下:
1. 创建数据模型
定义存储习惯信息的模型,实现Identifiable方便SwiftUI遍历:
struct Habit: Identifiable { let id = UUID() var habitName: String var display: Bool }
2. 修改ContentView的状态存储
把原来的HabitEggButton数组替换为Habit数据模型数组,用@State管理:
struct ContentView: View { @State private var habits: [Habit] = [ Habit(habitName: "Drink Water", display: true), Habit(habitName: "Gym", display: true), Habit(habitName: "Read a Book", display: true) ] var body: some View { VStack(spacing: 20) { // 遍历数据模型,传递状态绑定给视图 ForEach($habits) { $habit in HabitEggButton(habitName: habit.habitName, display: $habit.display) .onChange(of: habit.display) { isVisible in // 长按隐藏后,从数组中移除对应项 if !isVisible { habits.removeAll { $0.id == habit.id } } } } } .padding() } }
3. 调整HabitEggButton视图
移除不必要的Identifiable实现(现在遍历的是数据模型),保留@Binding接收状态绑定:
import SwiftUI struct HabitEggButton: View { var habitName: String @Binding var display: Bool var body: some View { Button(action: { print("\(habitName) button tapped") print(display ? "Yes" : "No") }) { Image("egg_uncracked") .resizable() .frame(width: 120, height: 120) } .supportsLongPress { display = false print("\(habitName) button held") } } }
原理说明
- 数据模型
Habit存储所有可变状态,ContentView用@State管理整个数组的变化。 - 通过
$habit.display将状态绑定传递给HabitEggButton,长按修改display值后,onChange会触发数组过滤操作,移除已隐藏的项,实现界面自动重新渲染。
内容的提问来源于stack exchange,提问作者Jesse Tzo
相关产品推荐
相关产品推荐

