微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在 SWIFT 中创建可绑定的自定义对象? 符合 ObservableObject

如何解决如何在 SWIFT 中创建可绑定的自定义对象? 符合 ObservableObject

XCode 版本 12.5 (12E262) - Swift 5

为了简化此示例,我创建了一个 testObj 类并向数组添加了一些项。 让我们假设我想在屏幕上渲染按钮(见下面的预览),一旦你点击按钮,它应该设置 testObj.isSelected = true 触发按钮改变背景颜色。

我知道它正在将值更改为 true,但是不会触发按钮更改其颜色。

示例如下:

//
//  TestView.swift
//
import Foundation
import SwiftUI
import Combine

struct TestView: View {
    
    @State var arrayOfTestObj:[testObj] = [
        testObj(label: "test1"),testObj(label: "test2"),testObj(label: "test3")
    ]

    var body: some View {
        vstack {
            ForEach(arrayOfTestObj,id: \.id) { o in
                HStack {
                    Text(o.label)
                        .width(200)
                        .padding(20)
                        .background(Color.red.opacity(o.isSelected ? 0.4: 0.1))
                        .onTapGesture {
                            o.isSelected.toggle()
                        }
                }
            }
        }
    }
}
  
class testObj: ObservableObject {
    let didChange = PassthroughSubject<testObj,Never>()
    
    var id:String = UUID().uuidString   {didSet {didChange.send((self))}}
    var label:String = ""               {didSet {didChange.send((self))}}
    var value:String = ""               {didSet {didChange.send((self))}}
    var isSelected:Bool = false         {didSet {didChange.send((self))}}
    
    init (label:String? = "") {
        self.label = label!
    }
}

struct TestView_Previews: PreviewProvider {
    static var previews: some View {
        TestView()
    }
}

如果我将 ForEach 更新为...

ForEach($arrayOfTestObj,id: \.id) { o in

...然后我收到此错误

键路径值类型“_”无法转换为上下文类型“_”

如何更改 testObj 以使其可绑定?

非常感谢任何帮助。

Test snippet to illustrate bindable custom object issue

解决方法

struct TestView: View {
    
    @State var arrayOfTestObj:[TestObj] = [
        TestObj(label: "test1"),TestObj(label: "test2"),TestObj(label: "test3")
    ]
    
    var body: some View {
        VStack {
            ForEach(arrayOfTestObj,id: \.id) { o in
                //Use a row view
                TestRowView(object: o)
            }
        }
    }
}
//You can observe each object by creating a RowView
struct TestRowView: View {
    //And by using this wrapper you observe changes
    @ObservedObject var object: TestObj
    var body: some View {
        HStack {
            Text(object.label)
                .frame(width:200)
                .padding(20)
                .background(Color.red.opacity(object.isSelected ? 0.4: 0.1))
                .onTapGesture {
                    object.isSelected.toggle()
                }
        }
        
    }
}
//Classes and structs should start with a capital letter
class TestObj: ObservableObject {
    //You don't have to declare didChange if you need to update manually use the built in objectDidChange
    let id:String = UUID().uuidString
    //@Published will notify of changes
    @Published var label:String = ""
    @Published var value:String = ""
    @Published var isSelected:Bool = false
    
    init (label:String? = "") {
        self.label = label!
    }
}

struct TestView_Previews: PreviewProvider {
    static var previews: some View {
        TestView()
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。