'How to convert Binding array value to Binding<[type]> instead of [Binding<type>] in Swift/SwiftUI
I have trouble with getting Binding values in correct format out of dataModel.
The XCode error I am getting is "Cannot convert value of type '[Binding<String?>]' to expected argument type 'Binding<[String]>'"
public final class RoomSelectionDataModel: ObservableObject {
@Published var roomsList: [Room]
@Published var selectedRoom: String?
}
public struct RoomSelectionView: View {
@StateObject var dataModel: RoomSelectionDataModel
public var body: some View {
let bindingArray = $dataModel.roomsList.compactMap { $0.name } // here the format is '[Binding<String?>]' instead of 'Binding<[String]>'
SelectionList(listElements: bindingArray,
backgroundColor: Color(red: 0.94, green: 0.94, blue: 0.94), // color to be removed
selectedElement: $dataModel.selectedRoom)
}
public init(dataModel: RoomSelectionDataModel) {
self._dataModel = StateObject(wrappedValue: dataModel)
}
}
public struct SelectionList: View {
let backgroundColor: Color
@Binding var listElements: [String]
@Binding var selectedElement: String?
public init(listElements: Binding<[String]>, backgroundColor: Color, selectedElement: Binding<String?>) {
self._listElements = listElements
self.backgroundColor = backgroundColor
self._selectedElement = selectedElement
}
}
public class Room: NSObject, Codable {
public var name: String?
}
The models are simplified here, to only have the relevant information.
Solution 1:[1]
Lets try explicitly creating the binding array as it seems you wish to:
let bindingArray = Binding<[String]>(
get: { dataModel.roomsList.compactMap { $0.name } },
set: { newValue in
let rooms = dataModel.roomsList.filter { $0.name != nil }
rooms.enumerated().forEach { numberedPair in
numberedPair.element.name = newValue[numberedPair.offset]
}
})
The get side of the binding is pretty straightforward. When you do the put side, things get a little more complicated. What my code does is assumes that the rooms are in the same order, that all the rooms which had names last time still have names, and that you're going to assign the names into the rooms that have them in their ordinal positions based on the new array.
All in all it's not clear why you want a Binding on the array because the put operation of [String] doesn't really match the model here.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Scott Thompson |
