swift - 如何在 SWIFT 中创建可绑定(bind)的自定义对象? (符合 ObservableObject)

标签 swift swiftui 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 使其可绑定(bind)?

非常感谢任何帮助。

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()
    }
}

关于swift - 如何在 SWIFT 中创建可绑定(bind)的自定义对象? (符合 ObservableObject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67379046/

相关文章:

ios - 为 XCTest 添加测试 Assets

swift - 单击按钮后计时器发布者初始化计时器

SwiftUI 可识别的 ForEach 最初从空开始时不会更新

SwiftUI ObservableObject 在发布值时不会更新

SwiftUI:ObservableObject 不适用于 fetchRequest init

swift - 向 API 发出重复请求

swift - 将用户的注意力吸引到 IOS 中的 UITextView

ios - 不能下标 [MPMediaItem] 类型的值

swift - SwiftUI 实时预览中的可变绑定(bind)

ios - 通过另一个 ObObject 传递 ObservableObject 模型?