ObservedObject, полученный из Json, не загружается в Picker, но загружается в List. В SwiftUI, Xcode 11 - PullRequest
2 голосов
/ 10 марта 2020

Я новичок в разработке мобильных приложений и в процессе изучения SwiftUI.

Я изо всех сил пытался выяснить, что не так с моим сборщиком. Я успешно возвращаю данные из моего URLSession и добавляю их в мою модель. Я могу подтвердить это, добавив мой @ObservedObject в список, который возвращает все элементы. Помещение того же @ObservedObject в средство выбора по какой-то причине возвращает пустое средство выбора. Любая помощь будет оценена. Спасибо.

Вот мой взгляд с помощью сборщика (). При запуске сборщик пуст. Я могу закомментировать Picker (), оставив только ForEach () с Text (), и появится текст.

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 к результатам запроса JSON в WebService (). Если я жестко закодирую переменную @Published в возвращаемое значение начало, средство выбора работает.

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 = $0
        }
    }

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

Вот мой WebService (). К сожалению, я не могу поделиться URL-адресом JSON, который я добавил в возвращаемом 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
}

1 Ответ

4 голосов
/ 10 марта 2020

Обходной путь для выбора ссылки sh - добавить уникальный идентификатор. Обновление (или) перезагрузка стран создаст новый UUID для элементов выбора. Это заставит сборщик перефразировать sh. Я изменил ваш код, добавив в него идентификатор.

//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())

Кажется, это известная проблема со сборщиком.

...