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

时间:2019-10-23 20:04:34

标签: swift swiftui

关于此主题有几个有用的问题,但是我发现所有这些都使用了早期Beta中不推荐使用的语法(例如BindableObject),或者不需要传递绑定(例如传递给Toggle)。

我想创建绑定到数组中元素的Toggles列表。我尝试了很多方法,但是语法永远不会正确。下面的版本与an existing question的答案最接近。

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

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

  

使用未解决的标识符'$ item'

在定义切换的行上。

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

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

您正在将items(这是当前值主题)的属性包装与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)
  }
}
相关问题