Skip to content

Instantly share code, notes, and snippets.

@ccwasden
Last active April 7, 2020 13:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ccwasden/9932edba37ed3f77f46c1e95402de7fe to your computer and use it in GitHub Desktop.
Save ccwasden/9932edba37ed3f77f46c1e95402de7fe to your computer and use it in GitHub Desktop.
Multiselect using ObservableObject with child array - Modified from child view through a Binding
struct Cheese: Identifiable {
let name: String
var isSelected: Bool
var id: String { name }
}
class ViewModel: ObservableObject {
@Published var cheeses = [
Cheese(name: "Brie", isSelected: false),
Cheese(name: "Cheddar", isSelected: true),
Cheese(name: "Gouda", isSelected: false),
]
}
struct CheeseList: View {
@ObservedObject var viewModel = ViewModel()
var body: some View {
VStack {
Text("Select Cheeses (\(viewModel.cheeses.filter { $0.isSelected }.count))")
BindingList(items: $viewModel.cheeses) { cheese in
CheeseRow(cheese: cheese)
}
}
}
}
struct CheeseRow: View {
@Binding var cheese: Cheese
var body: some View {
Button(action: { self.cheese.isSelected.toggle() }) {
HStack {
Text(cheese.isSelected ? "" : "")
Text(cheese.name)
}
}
}
}
// ----------- The Reusable Magic ----------- //
struct BindingList<T: Identifiable, V: View>: View {
@BindableArray var items: Binding<[T]>
let rowBuilder: ((Binding<T>) -> V)
var body: some View {
List($items, rowContent: rowBuilder)
}
}
extension Binding: Identifiable where Value: Identifiable {
public var id: Value.ID {
return wrappedValue.id
}
}
@propertyWrapper
struct BindableArray<Value> : DynamicProperty {
@Binding var storage: [Value]
init(wrappedValue value: Binding<[Value]>) {
self._storage = value
}
public var wrappedValue: Binding<[Value]> {
get { _storage }
nonmutating set { storage = newValue.wrappedValue }
}
public var projectedValue: [Binding<Value>] {
var bindings = [Binding<Value>]()
for (i, item) in storage.enumerated() {
bindings.append(Binding(
get: { item },
set: { self.wrappedValue[i].wrappedValue = $0 }
))
}
return bindings
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment