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

后端 未结 2 1721
逝去的感伤
逝去的感伤 2020-12-15 06:38

I\'m using an ObservableObject \'DataStore\', which contains an array (\'exampleList\') of objects (\'exampleObject\').

@Published exampleList = [exampleObjec         


        
相关标签:
2条回答
  • 2020-12-15 06:48

    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]()
    ...
    
    0 讨论(0)
  • 2020-12-15 06:52

    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))
        }
    }
    
    0 讨论(0)
提交回复
热议问题