Средство выбора SwiftUI не связывается с ObservedObject - PullRequest
1 голос
/ 18 апреля 2020

Я пытаюсь заполнить средство выбора асинхронно полученными данными из внешнего API.

Это моя модель:

struct AppModel: Identifiable {
    var id = UUID()
    var appId: String
    var appBundleId : String
    var appName: String
    var appSKU: String
}

Класс, который извлекает данные и публикует sh:

class AppViewModel: ObservableObject {
    private var appStoreProvider: AppProvider? = AppProvider()
    @Published private(set) var listOfApps: [AppModel] = []
    @Published private(set) var loading = false

    fileprivate func fetchAppList() {
        self.loading = true
        appStoreProvider?.dataProviderAppList { [weak self] (appList: [AppModel]) in
            guard let self = self else {return}
            DispatchQueue.main.async() {
                self.listOfApps = appList
                self.loading = false
            }
        }
    }
    init() {
        fetchAppList()
    }
}

Представление:

struct AppView: View {
    @ObservedObject var appViewModel: AppViewModel = AppViewModel()
    @State private var selectedApp = 0

    var body: some View {
        ActivityIndicatorView(isShowing: self.appViewModel.loading) {
            VStack{
                // The Picker doesn't bind with appViewModel
                Picker(selection: self.$selectedApp, label: Text("")) {
                    ForEach(self.appViewModel.listOfApps){ app in
                        Text(app.appName).tag(app.appName)
                    }
                }
                // The List correctly binds with appViewModel
                List {
                    ForEach(self.appViewModel.listOfApps){ app in
                        Text(app.appName.capitalized)
                    }
                }
            }
        }
    }
}

Хотя представление списка связывается с наблюдаемым объектом appViewModel, средство выбора не ведет себя так же. Я не могу понять почему. Любая помощь ?

1 Ответ

0 голосов
/ 18 апреля 2020

Я не могу вставить это в ваш код, потому что он неполный, но вот пример. Сборщики не должны быть динамичными c. Они должны быть полностью перезагружены.

class DynamicPickerViewModel: ObservableObject {
    @Published private(set) var listOfApps: [YourModel] = []
    @Published private(set) var loading = false

    fileprivate func fetchAppList() {
            loading = true
            DispatchQueue.main.async() {
                self.listOfApps.append(YourModel.addSample())
                self.loading = false
            }

    }
    init() {
        fetchAppList()
    }

}
struct DynamicPicker: View {
    @ObservedObject var vm = DynamicPickerViewModel()
    @State private var selectedApp = ""

    var body: some View {
        VStack{
            //Use your loading var to reload the picker when it is done
            if !vm.loading{
                //Picker is not meant to be dynamic, it needs to be completly reloaded
                Picker(selection: self.$selectedApp, label: Text("")) {
                    ForEach(self.vm.listOfApps){ app in
                        Text(app.name!).tag(app.name!)
                    }
                }
            }//else - needs a view while the list is being loaded/loading = true


            List {
                ForEach(self.vm.listOfApps){ app in
                    Text(app.name!.capitalized)
                }
            }

            Button(action: {
                self.vm.fetchAppList()
            }, label: {Text("fetch")})

        }
    }
}

struct DynamicPicker_Previews: PreviewProvider {
    static var previews: some View {
        DynamicPicker()
    }
}
...