我希望能够执行搜索、获取数据并导航到下一个屏幕并显示数据。通过按此顺序执行此操作,我可以确保在导航之前有数据。我遇到的问题是,在数据从搜索返回之前,我发送到第二个屏幕的值为零,并且我还没有找到处理此问题的好方法。在下面的代码中,我使用虚拟值初始化 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))
}
仅根据存在的数据有条件地添加
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: {}
)
}
这是一个关于 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
}
}
}
}