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())
这似乎是选择器的一个已知问题。
我是移动开发新手,正在学习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())
这似乎是选择器的一个已知问题。