SwiftUI ObservedObject Binding KeyPath 下标错误

标签 swift swiftui

我在尝试使用泛型类型 T 的 KeyPath 指定 @ObservedObject 的属性绑定(bind)时遇到编译器错误。

我正在尝试创建一个通用的 SwiftUI View ,该 View 适用于具有多个相同类型属性的类。 SwiftUI View 需要是通用的;但是我无法确定如何创建到通过 KeyPath 访问的主对象的属性的绑定(bind)。下面的代码返回错误“‘T’类型的值没有下标”

更新:我在代码中发现了错误,而不是 $model[keyPath: kp] 我应该使用 $model[dynamicMember: kp]。

import SwiftUI

class TestClass: ObservableObject {
    @Published public var str1: String = "one"
    @Published public var str2: String = "two"
}

struct ContentView: View { 

    @ObservedObject var test = TestClass()
    var body: some View {
        VStack {
            HStack{
                Text("String One").padding(20)
                StringView(model: test, kp: \TestClass.str1).padding(20)
            }
            HStack{
                Text("String Two").padding(20)
                StringView(model: test, kp: \TestClass.str2).padding(20)
            }
        }
    }
}

struct StringView<T>: View where T: ObservableObject {

    @ObservedObject var model: T

    var kp: ReferenceWritableKeyPath<T,String>

    init(model: T, kp: ReferenceWritableKeyPath<T,String>) {
        self.model = model
        self.kp = kp
    }

    var body: some View {
        HStack{
        TextField("String", text: $model[keyPath: kp])   <--- COMPILER ERROR HERE
        Text(model[keyPath: kp])
        }
    }
}

可以这样做吗?

最佳答案

我认为你可以通过以下方式做到这一点。 但我的想法有点冗长。

至少,TextField 需要 Binder。 所以KeyPath的目标Type应该是这样的。

class TestClass: ObservableObject {
  @Published public var str1: String = "one"
  @Published public var str2: String = "two"
}

struct _ContentView: View {

  @ObservedObject var test = TestClass()

  init() {

  }
  var body: some View {
    VStack {
      HStack{
        Text("String One").padding(20)
        StringView(model: test, kp: \ObservedObject<TestClass>.Wrapper.str1).padding(20)
      }
      HStack{
        Text("String Two").padding(20)
        StringView(model: test, kp: \ObservedObject<TestClass>.Wrapper.str2).padding(20)
      }
    }
  }
}

struct StringView<T>: View where T: ObservableObject {

  @ObservedObject var model: T

  var kp: ReferenceWritableKeyPath<ObservedObject<T>.Wrapper, Binding<String>>

  init(model: T, kp: ReferenceWritableKeyPath<ObservedObject<T>.Wrapper, Binding<String>>) {
    self.model = model
    self.kp = kp
  }

  var body: some View {
    HStack{
      TextField("String", text: $model[keyPath: kp])
      Text($model[keyPath: kp].wrappedValue)
    }
  }
}

关于SwiftUI ObservedObject Binding KeyPath 下标错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57984819/

相关文章:

ios - 即使我在 iOS 的另一个选项卡中,如何返回 Root View Controller ?

ios - SwiftUI:仅在 iOS 14+ 上使用 'accessibilityIdentifier'

swift - 在 SwiftUI 中使用三元运算符会导致类型不匹配错误,为什么?

swift - 为什么我在切换屏幕时会丢失我的 SwiftUI View

ios - Swift:锁定按钮位置,因为它被 UITextview 移动?约束问题?

swift - 动画 NSImageView 翻译

SwiftUI:如何制作 Lottie 动画循环?

使用 NavigationLink isActive 时 View 之间的动画不起作用

ios - 在不破坏表格 View 单元格点击功能的情况下关闭 iOS 键盘

swift - 自定义 UITabBarItem 的文本颜色和字体导致 swift 出现奇怪的结果