【发布时间】:2021-03-02 23:24:59
【问题描述】:
我正在尝试找到一种可行的方法来处理从异步回调返回的数据的导航。
考虑以下示例。 NavigationExampleView 中的按钮在一个单独的对象上触发了一些异步方法,在这种情况下是 NavigationExampleViewModel。从方法返回的数据,然后应该推送到导航堆栈中的UserView。 NavigationLink 似乎是存档的方法,但我找不到一种方法来获取我需要呈现的数据的非可选值。
struct User: Identifiable {
let id: String
let name: String
}
protocol API {
func getUser() -> AnyPublisher<User, Never>
}
struct NavigationExampleView: View {
@ObservedObject var vm: NavigationExampleViewModel
var body: some View {
HStack {
Button("Get User") {
vm.getUser()
}
NavigationLink.init(
destination: UserView(user: ???),
isActive: ???,
label: EmptyView.init
)
}
}
}
class NavigationExampleViewModel: ObservableObject {
@Published var isLoading = false
@Published var pushUser: User?
var cancellable: AnyCancellable?
let api: API
init(api: API) { self.api = api }
func getUser() {
isLoading = true
cancellable = api.getUser().sink { user in
self.pushUser = user
self.isLoading = false
}
}
}
struct UserView: View, Identifiable {
let id: String
let user: User
var body: some View {
Text(user.name)
}
}
问题:
- 如何获取数据以在视图中显示为非可选值?
- 我应该使用什么作为绑定来控制演示?
我几乎可以将其存档的一种方法是使用视图修饰符.sheet(item: Binding<Identifiable?>, content: Identifiable -> View),如下所示:
struct NavigationExampleView: View {
@ObservedObject var vm: NavigationExampleViewModel
var body: some View {
HStack {
Button("Get User") {
vm.getUser()
}
}.sheet(item: $vm.pushUser, content: UserView.init)
}
}
如何归档相同的视图以将视图推送到导航堆栈,而不是将其呈现为工作表?
【问题讨论】:
-
我会给 UserView 提供多种状态,例如“未加载”、“正在加载”、“已加载”。然后将 API 发布者直接传递给 userView 和 .onAppear { API.getUser }。所以当 UserView 出现时,它会立即开始加载,并在 api 返回时显示数据。这里解释得很好:swiftbysundell.com/articles/handling-loading-states-in-swiftui
-
这并不能解决我的问题:/ 如果应该推送的特定视图取决于返回的数据怎么办。例如,如果我想为管理员用户呈现一些特定的视图,而为不是管理员的用户呈现一些完全不同的视图。
-
制作一个异步用户容器视图,就像我上面的评论一样。然后制作另外两个视图结构(非管理员和管理员)。容器视图将确定用户是否是管理员,并将数据传递并显示到适当的用户视图(管理员或非管理员)
-
加载完成后我需要推送视图。
-
如果你想做类似的事情,你必须做一些额外的工作来制作某种自定义绑定以与 sheetCoverView 一起使用。我不认为这是一个好的设计模式。如果用户单击预期的东西并且会发生操作并且在加载数据之前没有任何反应,那么用户将会感到困惑。以“苹果音乐”为例。点击相册时,视图会立即呈现,相册在加载时会显示。
标签: swift swiftui navigation