SwiftUI - 从网络接收数据后进行导航

问题描述 投票:0回答:2

我希望能够执行搜索、获取数据并导航到下一个屏幕并显示数据。通过按此顺序执行此操作,我可以确保在导航之前有数据。我遇到的问题是,在数据从搜索返回之前,我发送到第二个屏幕的值为零,并且我还没有找到处理此问题的好方法。在下面的代码中,我使用虚拟值初始化 viewModel.weather 以摆脱可选值。

第一次查看片段:

@StateObject var viewModel = SearchViewModel()
    
    var body: some View {
        NavigationView {
            ZStack {
                NavigationLink(
                    destination: CityWeatherView(weather: viewModel.weather),
                    isActive: $viewModel.navigateToWeatherView,
                    label: {}
                )

搜索视图模型:

class SearchViewModel: ObservableObject, LocationDelegate {
    
    @Published var searchText = ""
    @Published var weather: OneCallWeatherModel = OneCallWeatherModel.testData

第二个视图

struct CityWeatherView: View {
    
    @StateObject private var viewModel: CityWeatherViewModel
    
    init(weather: OneCallWeatherModel) {
        _viewModel = StateObject(wrappedValue: CityWeatherViewModel(weather: weather))
    }
swiftui network-programming
2个回答
0
投票

仅根据存在的数据有条件地添加

NavigationLink
,例如

class SearchViewModel: ObservableObject, LocationDelegate {
    
    @Published var searchText = ""
    @Published var weather: OneCallWeatherModel?     // << optional
...
} 

这是用法

ZStack {
   if viewModel.weather != nil { // next will be instantiated when data got fetched
        NavigationLink(
            destination: CityWeatherView(weather: viewModel.weather!),
            isActive: $viewModel.navigateToWeatherView,
            label: {}
        )
   }

0
投票

这是一个关于 navigationDestination 的高级想法。这个想法是有一个加载屏幕,并仅在数据准备好后才显示真实屏幕。

@State var objects: [Object] = []
@State var isLoaded: Bool = false

List {
    ForEach(objects, id: \.self) { obj in
        NavigationLink(obj.name, value: invoice)
    }
}
.navigationDestination(for: Object.self) { obj in
            if isLoaded {
                Text("Is Loaded")
            } else {
                Text("Loading...")
                    .task {
                        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + .seconds(1)) {
                            isLoaded = true
                        }
                    }
            }
}
© www.soinside.com 2019 - 2024. All rights reserved.