【问题标题】:Forcing a view to unload or don't be displayed when a list has no items当列表没有项目时强制视图卸载或不显示
【发布时间】:2021-08-19 17:28:19
【问题描述】:

我有一个基于数组成员的NavigationLink 列表。当您单击列表项时,下一个视图会加载到右侧,显示该特定项的数据。 删除项目时,会显示下一个项目。但是,当您删除列表中的所有项目时,最后一个项目的数据仍留在加载的视图中。我试图查看选定的项目是否为零,或者检查是否选择了某些其他形式,或者列表至少有一个项目,但我不知道如何检查所有这些并卸载视图。

代码如下:

        @State var selectedNoteId: UUID?

        NavigationView {
            List(data.notes) { note in
                NavigationLink(
                    destination: NoteView(note: note),
                    tag: note.id,
                    selection: $selectedNoteId
                ) {
                    VStack(alignment: .leading) {
                        Text(note.text.components(separatedBy: NSCharacterSet.newlines).first!).font(.body).fontWeight(.bold)
                        Text(note.dateText).font(.body).fontWeight(.light)
                    }
                    .padding(.vertical, 10)
                }
            }
            .listStyle(InsetListStyle())
            .frame(minWidth: 250, maxWidth: .infinity)

            Text("Select a note or create a new one...")
                .frame(maxWidth: .infinity, maxHeight: .infinity)
        }
        .navigationTitle("A title")

如何卸载NoteView 并返回显示Text("Select a note or create a new one...")

感谢您的帮助!

已编辑:

这就是我删除数据的方式:

func removeNote() {
        if let selection = selectedNoteId,
           let selectionIndex = data.notes.firstIndex(where: { $0.id == selection }) {
            //print("DEBUG: delete item: \(selectionIndex)")
            data.notes.remove(at: selectionIndex)
        }
    }

【问题讨论】:

  • 这是否回答了您的问题stackoverflow.com/a/62907153/12299030
  • 谢谢,但没有。我的问题不是删除一个项目,或者从另一个视图中删除,而是,一旦 NavigationLinks 上的列表为空,因为我删除了那里的每个项目,卸载留下的 NoteView 视图显示来自的文本最后一个(现在消失了)笔记。

标签: swift swiftui


【解决方案1】:

你可以用if包裹整个列表

NavigationView {
    if !data.notes.isEmpty {
        List(data.notes) { note in
            NavigationLink(
                destination: NoteView(note: note),
                tag: note.id,
                selection: $selectedNoteId
            ) {
                VStack(alignment: .leading) {
                    Text(note.text.components(separatedBy: NSCharacterSet.newlines).first!).font(.body).fontWeight(.bold)
                    Text(note.dateText).font(.body).fontWeight(.light)
                }
                .padding(.vertical, 10)
            }
        }
        .frame(minWidth: 250, maxWidth: .infinity)
    } else {
        List(data.notes) { _ in EmptyView() }
    }
    Text("Select a note or create a new one...")
        .frame(maxWidth: .infinity, maxHeight: .infinity)
}
.listStyle(InsetListStyle())
.navigationTitle("A title")
.onAppear {
    DispatchQueue.main.async {
        selectedNoteId = data.notes.first?.id
    }
    DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
        data.notes.removeAll()
    }
}

notes 为空时,不会调用列表的内容。不关闭旧的导航链接,看起来 macOS 有很多问题

【讨论】:

  • 谢谢菲利普,我已经试过了。如果你是一个项目列表,你删除它们,视图仍然被留下,这是我试图解决的问题。这就是为什么我问如何卸载或关闭视图。有趣的是,如果您在任何 NavigationLinks 之外的空白区域单击列表本身,NotesView 就会消失,并且会显示“单击...”文本...。
  • @Aleph 你确定你试过这个吗?我已经仔细检查过,删除项目后 NavigationLink 项目与我的 if 一起消失
  • 不,看起来不一样,你是对的。但是,当数组为空时,列表根本不显示,所以现在列表的占位符是灰色的。当然,我可以将颜色设置为白色或默认值,但我认为这个解决方案稍后会回来并产生问题......我无法完全说明原因。我有一个截图,但我似乎无法上传它。我很惊讶视图被抛在后面,而且没有清理......
  • @Aleph 我明白了,这看起来是因为背景是由InsetListStyle 设置的。所以一个可能的解决方案是在else 分支中添加另一个列表。这段代码看起来更丑=)更新了我的答案,也将.listStyle(InsetListStyle()) 移动到它会影响两个列表
  • Philip,我还没有尝试过代码,但我确实找到了一个 hack。请参阅我对问题的回答。代码少了一点。
【解决方案2】:

这样的东西会起作用吗?我不确定当用户删除数据时您实际上是如何删除数据的。

List(data.notes) { note in
        if data.notes.isEmpty {
            navlink
        } else {
            Text("Select a note or create a new one...")
                .frame(maxWidth: .infinity, maxHeight: .infinity)
        }
    }

【讨论】:

  • 我编辑了我的问题,请参阅上面我如何删除数据。谢谢!
  • @Aleph 我的 if else 应该可以工作,我已经以与您相同的方式删除了数据,并使用 if else 来显示和更新基于数组的视图。尝试后告诉我。
  • 谢谢。这没用。首先,您需要添加not,如!if data.notes.isEmpty,否则当您有数据时,它将使用Text("Select a note or create a new one...") 填充列表。其次,如果您查看代码,文本不会显示为列表的一部分,而是显示在新视图所在的位置(如果有要显示的数据)。我添加了 not (!) 并将 if 移动了一点,但是当您删除所有内容时,它仍然留下 NoteView 以及最后一条注释的文本。我需要卸载NoteView,不显示任何文字。
【解决方案3】:

所以,我找到了一种更清洁的方法。添加扩展:

extension View {
    @ViewBuilder func hidden(_ shouldHide: Bool) -> some View {
        switch shouldHide {
        case true: self.hidden()
        case false: self
        }
    }
}

然后在NoteView打电话:

.hidden(data.notes.isEmpty)

当数据为空时,视图将消失。 我想这是一个丑陋的黑客,但不知何故,当列表中没有项目时,最后一个视图被抛在后面,我找不到任何其他方法来强制它卸载。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多