如何在 SwiftUI 中使用 ObservedObject 制作 Picker?

jar*_*aez 1 swiftui

我正在尝试从 Rest API 获取数据中心列表并将它们显示在选择器中,以便用户可以选择一个。当我用静态列表做它时,它工作正常。但是,动态检索数据中心似乎效果不佳。

我正在使用 Xcode 11 (GM)

这是数据中心对象

struct Datacenter:Codable, Hashable, Identifiable{ 
    let id: String
    var location: String
}
Run Code Online (Sandbox Code Playgroud)

这是 ObservedObject(它的属性 datacenters 是一个 Datacenter 对象数组)

@ObservedObject var datacenters_controller : DatacentersController
@State private var selectedDatacenter = 0
Run Code Online (Sandbox Code Playgroud)

这是我的第一次尝试:

Picker(selection: $selectedDatacenter, label: Text("Datacenter")) {
   ForEach(0 ..< datacenters_controller.datacenters.count) {
     Text(self.datacenters_controller.datacenters[$0].location)
   }
}
Run Code Online (Sandbox Code Playgroud)

Swift 抱怨以下错误:

ForEach<Range<Int>, Int, Text> count (4) != its initial count (0). `ForEach(_:content:)` should only be used for *constant* data. Instead conform data to `Identifiable` or use `ForEach(_:id:content:)` and provide an explicit `id`!
Run Code Online (Sandbox Code Playgroud)

然后我切换到:

ForEach<Range<Int>, Int, Text> count (4) != its initial count (0). `ForEach(_:content:)` should only be used for *constant* data. Instead conform data to `Identifiable` or use `ForEach(_:id:content:)` and provide an explicit `id`!
Run Code Online (Sandbox Code Playgroud)

它“有效”(没有错误),但结果不是预期的,因为虽然我可以选择一个数据中心,但它没有“存储”,也没有在选择器中显示为选定的。

实际结果

没有选择的选择器

预期结果

选择了数据中心的选择器

任何的想法?我做错了什么?

Joh*_* M. 5

这是一个工作示例。关键是 selectedDatacenter 需要与 Datacenter.id 的类型相同(在本例中为 String)。

struct ContentView: View {
    @ObservedObject var datacenters_controller = DatacentersController()
    @State private var selectedDatacenter = ""

    var body: some View {
        NavigationView {
            Form {
                Picker(selection: $selectedDatacenter, label: Text("Datacenter")) {
                    ForEach(datacenters_controller.datacenters) { datacenter in
                        Text(datacenter.location)
                    }
                }

                // Just here for demonstration
                Text("selectedDatacenter (id): \(selectedDatacenter.isEmpty ? "Nothing yet" : selectedDatacenter)")
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是支持代码

struct Datacenter:Codable, Hashable, Identifiable{
    let id: String
    var location: String
}

class DatacentersController: ObservableObject {
    @Published var datacenters: [Datacenter] = []

    init() {
        datacenters = [
            Datacenter(id: "ABQ", location: "Albuquerque"),
            Datacenter(id: "BOS", location: "Boston"),
            Datacenter(id: "COS", location: "Colorado Springs")
        ]
    }
}
Run Code Online (Sandbox Code Playgroud)