Binding an element of an array of an ObservableObject : 'subscript(_:)' is deprecated
Xcode 11, beta 6 UPDATE:
Good news! Just as I suspected, in beta 6, the Binding
conformance to MutableCollection
has been been replaced with something else. Instead of conforming to MutableCollection, it now let your access the elements via @dynamicMemberLookup
. The result is you now can keep doing $text[3]
and no longer get a warning! It seems this question can be closed now.
Xcode 11, beta 5. Old answer:
I finally got some time to investigate this a little. As I mentioned in the comments, I think it would be wise to wait until the Collection
conformance is completely removed (or replaced with something else). But just to satisfy our curiosity, I have created an extension on Binding
, that I think does what the current Collection
conformance does. The only difference is that, instead of accessing through a subscript, I implemented a function called element(_ idx: Int)
to get a Binding<T>
to the element.
If one day the conformance is completely removed, I may change the implementation, and conform to Collection
myself. I cannot do it now, because it would conflict with the existent (and deprecated) implementation. For the time being, I think this demonstrate how to handle the warnings if you absolutely want to get rid of them.
Just to be clear. I am not using this code. As long as I can still access the elements through the subscript, I will still do it and ignore the warnings. This is just for academic purposes.
The extension is:
extension Binding where Value: MutableCollection, Value.Index == Int { func element(_ idx: Int) -> Binding<Value.Element> { return Binding<Value.Element>( get: { return self.wrappedValue[idx] }, set: { (value: Value.Element) -> () in self.wrappedValue[idx] = value }) }}
And it can be used like this:
struct MainView: View { @Binding var text: [String] var body: some View { TextField("", text: $text.element(0)) TextField("", text: $text.element(1)) TextField("", text: $text.element(2)) }}
I had to bind the array of an observable object recently, didn't get any warnings on stable XCode11. I did it like this
struct ScheduleTimer: Identifiable { var id: Int var name: String var start: Date var end: Date var isActive: Bool}struct ScheduleView: View { @ObservedObject var scheduleController = ScheduleController() var body: some View { NavigationView { Form { ForEach(scheduleController.timers) { timer in ScheduleForm(scheduleController: self.scheduleController, timer: timer) } } } }}struct ScheduleForm: View { @ObservedObject var scheduleController: ScheduleController var timer: ScheduleTimer var scheduleIndex: Int { scheduleController.timers.firstIndex(where: { $0.id == timer.id })! } @State var start = Date() var body: some View { Section(header: Text(self.scheduleController.timers[scheduleIndex].name)){ DatePicker("From", selection: self.$scheduleController.timers[scheduleIndex].start, displayedComponents: .hourAndMinute) DatePicker("To", selection: self.$scheduleController.timers[scheduleIndex].end, displayedComponents: .hourAndMinute) Toggle(isOn: self.$scheduleController.timers[scheduleIndex].isActive) { Text("") }.toggleStyle(DefaultToggleStyle()) } }}class ScheduleController: ObservableObject { @Published var timers = [ScheduleTimer]()...