Binding an element of an array of an ObservableObject : 'subscript(_:)' is deprecated Binding an element of an array of an ObservableObject : 'subscript(_:)' is deprecated swift swift

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]()...