Swift 绑定可观察对象数组的元素:';下标';不赞成

Swift 绑定可观察对象数组的元素:';下标';不赞成,swift,swiftui,xcode11,Swift,Swiftui,Xcode11,我使用的是一个ObserveObject“DataStore”,它包含一个对象数组('exampleList')('exampleObject') 我通过@EnvironmentObject('DataStore')调用数据存储 然后我用 ForEach(0..<dataStore.exampleList.count) { index in .... 在Xcode11Beta4之前,它工作得非常好。自Xcode 11 beta 5以来,它仍能正常工作,但Xcode向我发出以下警告: 不推

我使用的是一个ObserveObject“DataStore”,它包含一个对象数组('exampleList')('exampleObject')

我通过@EnvironmentObject('DataStore')调用数据存储

然后我用

ForEach(0..<dataStore.exampleList.count) { index in ....
在Xcode11Beta4之前,它工作得非常好。自Xcode 11 beta 5以来,它仍能正常工作,但Xcode向我发出以下警告:

不推荐使用“subscript(\)”:有关迁移路径,请参阅发行说明

我尝试了更简单的东西,使用了一个简单的@State变量,它包含一个字符串数组,这是相同的问题:当调用这个数组的一个元素,并尝试将该值用于TextField时:

TextField("test", text: $test[0])
我也得到同样的警告

我不知道如何修理它。这是否意味着我们不再可以在数组中绑定值? 那么,我们如何迭代一个数组并绑定一个特定的项呢

这是我关于堆栈溢出的第一个问题,如果我的问题很笨拙,我很抱歉。。。
非常感谢您的回答,我使用堆栈溢出已经很多年了,这很神奇,我总是能找到现有的和有用的答案,但这是我第一次找不到任何答案,这就是我为什么要问的原因。

Xcode 11,beta 6更新:

好消息!正如我所怀疑的,在beta 6中,
绑定
可变集合
的一致性已经被其他东西所取代。它不再遵从MutableCollection,而是允许您通过
@dynamicMemberLookup
访问元素。结果是您现在可以继续执行
$text[3]
,而不再收到警告!看来这个问题现在可以解决了

Xcode 11,beta 5。旧答案:

我终于有时间调查一下了。正如我在评论中提到的,我认为明智的做法是等到
集合
的一致性被完全删除(或者用其他东西替换)。但为了满足我们的好奇心,我在
绑定
上创建了一个扩展,我认为它与当前的
集合
一致性一样。唯一的区别是,我没有通过下标进行访问,而是实现了一个名为
element(\uidx:Int)
的函数,以获得对元素的
绑定

如果有一天一致性被完全删除,我可能会更改实现,并遵从
集合
我自己。我现在不能这样做,因为它会与现有的(和不推荐的)实现冲突。就目前而言,我认为这将演示如何处理警告,如果你绝对想消除它们的话

我只是想说清楚。我没有使用这个代码。只要我仍然可以通过下标访问元素,我仍然会这样做并忽略警告。这只是出于学术目的。

延长期限为:

扩展绑定,其中Value:MutableCollection,Value.Index==Int{
func元素(idx:Int)->绑定{
返回绑定(
获取:{
返回self.wrappedValue[idx]
},在中设置:{(值:value.Element)->()
self.wrappedValue[idx]=值
})
}
}
它可以这样使用:

DetailView(itemBinding: $dataStore.exampleList[index])
struct MainView:View{
@绑定变量文本:[字符串]
var body:一些观点{
TextField(“,text:$text.element(0))
TextField(“,text:$text.element(1))
TextField(“,text:$text.element(2))
}
}

我最近不得不绑定一个可观察对象的数组,在稳定的XCode11上没有收到任何警告。我是这样做的

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

首先,好问题。我对此进行了升级,因为我得到了一个类似的带有
滑块的警告。我发现了与您相同的事情-如果您绑定到
ObservableObject
中的数组,则可能有问题(但仍然有效),但如果您绑定到局部状态变量,则一切都很好(但如何更新模型?)。我有一个样本项目,如果你想检查出来(忽略名称,这是一个老问题)。如果我找到答案,我会发布。@dfd,谢谢你的评论,我很高兴知道我不是世界上唯一一个有这个问题的人。我仍然不明白为什么,因为对于具有复杂数据的模型来说,使用数组似乎是一种常见的情况。对我来说,ObserveObject的兴趣在于在修改数组元素时刷新所有父视图。如果我不能再这样做了,那好的方法是什么?这不是我今天想做的,但在花了一个小时(我的生命中,我再也回不来了)后,我找不到答案。我听了一些与苹果相关的播客,昨天有一个播客在谈论“软件”是如何落后于“硬件”的,他们在思考苹果9月份可能会做些什么。我拿什么?我的应用程序在beta 4和beta 5中都出现了重大突破,因为这些变化对我来说毫无意义。现在我正在看(a)一些带有警告的东西,(b)不知道beta 6在10天内会有什么变化。与此同时,我将关注您的问题。从beta 5的发行说明中:绑定结构与收集协议的条件一致性被删除。(51624798). 确切地说,它没有被删除,而是被弃用了。这就是为什么它仍然有效。如果他们遵循与其他beta版本相同的模式,他们可能会在beta版本6或7中永久删除它。我没有时间分析其他选择。发行说明中列举了一些例子,但它们似乎做了太多的工作,无法实现迄今为止如此简单的目标。我打赌(续)我打赌在beta 6或beta 7中情况会再次发生变化。也许与该系列的一致性不会回来,但可能会提供一些东西。虽然它仍然有效,但我不想浪费太多时间研究它。如果很快又有变化,一切可能都是徒劳的。目前,我想我会把它放在一边,担心他们最终删除它。我遇到了
dyld:Symbol not found:$s7Swi的问题
TextField("test", text: $test[0])
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]()
...