如何从对象数组创建切换绑定?

dro*_*ang 1 swift swiftui

关于这个主题有几个有用的问题,但我发现要么使用早期测试版中已弃用的语法(例如,BindableObject),要么不需要传递绑定(例如,到 Toggle)。

我想创建一个绑定到数组中元素的切换列表。我尝试了很多方法,但语法总是不正确。下面的版本与现有问题的答案最接近。

struct Item: Identifiable {
    var id: String { self.name }
    var name: String
    var enabled: Bool
}

final class ItemSet: ObservableObject {
    @Published var items: [Item]

    init() {
        items = [
            Item(name: "aaa", enabled: true),
            Item(name: "bbb", enabled: false),
            Item(name: "ccc", enabled: true)
        ]
    }
}

var myItems = ItemSet()

struct ContentView: View {
    @ObservedObject var items: ItemSet

    var body: some View {
        List {
            ForEach(items.items) { item in
                Toggle(item.name, isOn: $item.enabled)
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView(items: myItems)
    }
}
Run Code Online (Sandbox Code Playgroud)

我在 Xcode 11.1 中遇到的编译器错误是:

使用未解析的标识符“$item”

在定义 Toggle 的行上。

我的印象是每个Item本身都需要带有ObservableObject参数@Published var enabled: Bool,但我也无法使其工作,并且所有 stackoverflow 答案似乎都说避免制作Item自身ObservableObject

任何帮助将非常感激。

Jos*_*ann 5

您将属性包装器items(它是当前值主题)与 a 期望的绑定参数混淆了Toggle。请参阅下面的绑定的更正实现:

import SwiftUI
import Combine

struct Item: Identifiable {
  var isEnabled: Binding<Bool>
  var id: String { self.name }
  var name: String
  init(name: String, enabled enabledValue: Bool) {
    self.name = name
    let enabled = CurrentValueSubject<Bool, Never>(enabledValue)
    isEnabled = Binding<Bool>(
      get: { enabled.value },
      set: { enabled.value = $0}
    )
  }
}

final class ItemSet: ObservableObject {
  @Published var items: [Item]

  init() {
    items = [
      Item(name: "aaa", enabled: true),
      Item(name: "bbb", enabled: false),
      Item(name: "ccc", enabled: true)
    ]
  }
}

var myItems = ItemSet()

struct ContentView: View {
  @ObservedObject var items: ItemSet

  var body: some View {
    List {
      ForEach(items.items) { item in
        Toggle(isOn: item.isEnabled, label: { Text (item.name) })
      }
    }
  }
}

struct ContentView_Previews: PreviewProvider {
  static var previews: some View {
    ContentView(items: myItems)
  }
}
Run Code Online (Sandbox Code Playgroud)