Swift UI:当视图中显示空列表时,如何显示错误消息?
Posted
技术标签:
【中文标题】Swift UI:当视图中显示空列表时,如何显示错误消息?【英文标题】:Swift UI: How do I display an error message when an empty List is displayed in a View? 【发布时间】:2021-04-25 20:06:35 【问题描述】:我有一组Terms
,按字母顺序分组。下面的 Swift UI 代码将集合显示为 List
,按组划分为多个部分。每个组都根据(可能为空的)搜索字符串进行过滤。因此显示的列表包含Terms
的整个集合、基于搜索字符串的子集,或者不包含任何内容(如果搜索失败):
var body: some View
List()
ForEach(terms.groups) group in
let groupTerms = filteredTerms(for: group)
if searchText.isEmpty || !groupTerms.isEmpty
Section(header: Text(group.name))
ForEach(groupTerms) term in
NavigationLink(destination: DetailView(term: term))
TermsRow(term: term)
问题是:我如何显示搜索失败的消息,而不是只显示一个空屏幕?可以确定,只有在外部 ForEach
循环完成且所有 groupTerms
为空时,搜索才会失败,但我无法捕获该信息——如果我贴上@,Swift 不喜欢它ForEach
循环中的 987654327@ 布尔值设置为 true
,如果任何 groupTerms
非空,如下所示:
var searchSucceeded = false
var body: some View
List()
ForEach(terms.groups) group in
let groupTerms = filteredTerms(for: group)
if searchText.isEmpty || !groupTerms.isEmpty
Section(header: Text(group.name))
ForEach(groupTerms) term in
NavigationLink(destination: DetailView(term: term))
TermsRow(term: term)
else if !searchText.isEmpty && !groupIdioms.isEmpty
searchSucceeded = true
// Display message here if searchSucceeded is false
此代码不会在分配给searchSucceeded
的情况下编译。我是 Swift UI 新手。最初的代码是由另一个不再可用的开发人员编写的。我希望有人可以在这里帮助我。
【问题讨论】:
SwiftUI 是一个 UI 框架。它不应该做任何工作searchSucceeded = true
算作工作。let groupTerms = filteredTerms(for: group)
算作工作。将所有“工作”代码移出 SwiftUI 视图并将其放入 class ViewModel
。 struct
是不可变的 var searchSucceeded = false
这永远不会按原样变异。在您的ViewModel
中将其设为@Published var
【参考方案1】:
与其尝试在ForEach
中设置searchSucceeded
,不如创建一个名为displayError
的计算属性来确定是否应显示错误。计算的属性将在每次渲染视图时重新计算,这会受到新属性、@State 更改等的影响。
var displayError : Bool
//condition here -- map? reduce?
return true
var body: some View
List()
ForEach(terms.groups) group in
let groupTerms = filteredTerms(for: group)
if searchText.isEmpty || !groupTerms.isEmpty
Section(header: Text(group.name))
ForEach(groupTerms) term in
NavigationLink(destination: DetailView(term: term))
TermsRow(term: term)
if displayError
Text("error message")
你没有包含你的模型代码,所以很难说在那个计算属性中放了什么,但是从你的循环来看,它很可能是一个reduce
或者迭代你的组并查看的东西如果有有效数据。
就像 cmets 中提到的 @lorem 一样,您可以将这种东西移动到视图模型中,但这并不是绝对必要的。如果您有大量数据并且出于资源原因想要限制通过数据的次数,这可能会变得更加重要。
【讨论】:
【参考方案2】:对于这样的情况 - 您必须绘制完全不同的“This”或“That”,我使用“EitherView”和相应的模型“Either”:
struct EitherView<Right: ComponentView, Left: ComponentView>: ComponentView
var state: Either<Right.State, Left.State>
init(_ state: Either<Right.State, Left.State>)
self.state = state
var body: some View
switch state
case .right(let right):
Right(right)
case .left(let left):
Left(left)
public enum Either<Right, Left>
case right(Right)
case left(Left)
然后您可以添加模态呈现的视图和加载指示器,如下面的示例所示,旨在实现一个可重用的通用视图来执行所有这些操作:
struct MyView<ContentView: ComponentView>: View
typealias Content = ContentView.State
typealias Modal = ModalState<AlertState, SheetState, ActionSheetState, LoadingState>
private var state: ViewState<Content, Modal>
init(_ state: ViewState<Content, Modal>)
self.state = state
var body: some View
return GeometryReader geometry in
ContentView(state.body)
.frame(width: geometry.size.width,
height: geometry.size.height,
alignment: .center)
.alert(item: showAlert) alert in
SwiftUI.Alert(title: Text(alert.title),
message: Text(alert.message))
.sheet(item: showSheet) sheet in
...
.actionSheet(item: showActionSheet) actionSheet in
SwiftUI.ActionSheet(title: Text(actionSheet.title))
private extension MyView
var showAlert: Binding<AlertState?>
Binding<AlertState?>(
get: self.state.alert ,
set: _ in self.state.dismiss()
)
...
请注意,此示例中的视图状态是不可变的。
为了将这个应用到您的问题中,您只需要编写相应的 model 或 viewState,最好在视图之外,例如在 viewModel 中。
现在你已经把你的大问题分成小块,每个小块都很容易解决。
【讨论】:
以上是关于Swift UI:当视图中显示空列表时,如何显示错误消息?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Swift UI 中将嵌套的 JSON 值显示到选取器视图中?
Swift 中的 Xcode:导航栏未显示在 UI 集合视图(模拟器)中
如果变量不是 nil,如何在 swift UI 中显示文本视图?