ObservedObject,派生自Json,不加载到Picker,而是加载到List。在 SwiftUI 中,Xcode 11

ObservedObject, derived from Json, not loading into Picker, but loads in List. In SwiftUI, Xcode 11

我是移动开发新手,正在学习SwiftUI。

我一直在努力找出我的选择器出了什么问题。我成功地从我的 URLSession 返回数据,并将其添加到我的模型中。我可以通过将我的 @ObservedObject 添加到列表中来确认这一点,其中 returns 所有项目。由于某种原因,将相同的@ObservedObject 放入一个选择器 returns 一个空的选择器中。任何帮助,将不胜感激。谢谢。

这是我对 Picker() 的看法。 运行时,Picker为空。我可以注释掉 Picker(),只留下带有 Text() 的 ForEach(),文本就会出现。

import Foundation
import Combine
import SwiftUI

struct ContentView: View {

@ObservedObject var countries = CulturesViewModel()
@State private var selectedCountries = 0

    var body: some View {

        VStack {

            //loop through country array and add them to picker
            Picker(selection: $selectedCountries, label: Text("Select Your Country")) {
                ForEach(0 ..< countries.cultures.count, id: \.self) { post in
                    Text(self.countries.cultures[post].Culture).tag(post)
               }
            }.labelsHidden()     
        }

    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

这是我的 ViewModel。它将@Published 变量设置为WebService() 中JSON 请求的结果。如果我将 @Published 变量硬编码为 begin 返回的值,选择器就会工作。

import Foundation
import Combine
import SwiftUI

class CulturesViewModel: ObservableObject {
    init() {
        fetchCultures()
    }

    @Published var cultures = [Culture](){
        didSet {
            didChange.send(self)
        }
    }

    private func fetchCultures(){
        WebService().GetCultures {
            self.cultures = [=13=]
        }
    }

    let didChange = PassthroughSubject<CulturesViewModel, Never>()
}

这是我的 WebService()。不幸的是,我无法分享 JSON url,我已在返回的 json 中添加。

import Foundation
import SwiftUI
import Combine

class WebService {

    func GetCultures(completion: @escaping([Culture]) ->()) {

        guard let url = URL("")

        [
            {
                "CultureId": 0,
                "Culture": "Select Your Country"
            },
            {
                "CultureId": 1078,
                "Culture": "English (United States)"
            },
            {
                "CultureId": 6071,
                "Culture": "English (Canada)"
            }
        ]

        URLSession.shared.dataTask(with: url) { (data,_,_) in
            do {
                if let data = data {
                    let culturesList = try JSONDecoder().decode([Culture].self, from: data)
                    DispatchQueue.main.async {
                        completion(culturesList)
                    }
                } else {
                    DispatchQueue.main.async {
                        completion([])
                    }
                }

            } catch {
                print(error)
                DispatchQueue.main.async {
                    completion([])
                }
            }
        }.resume()
    }
}

最后,这是我的模型。

import Foundation

struct Culture: Codable, Identifiable {
    var id = UUID()
    var CultureId: Int
    var Culture: String
}

使选择器刷新的解决方法是添加一个唯一 ID。刷新(或)重新加载国家,将为选择器项目创建一个新的 UUID。这将强制选择器刷新。我已经修改了您的代码以包含一个 ID。

//loop through country array and add them to picker
Picker(selection: $selectedCountries, label: Text("Select Your Country")) {
    ForEach(0 ..< countries.cultures.count, id: \.self) { post in
        Text(self.countries.cultures[post].Culture).tag(post)
   }
}.labelsHidden()
.id(UUID())

这似乎是选择器的一个已知问题。