如何在SwiftUI中制作一个层次结构的侧栏,其中的子元素与父元素的类型不同?

oknwwptz  于 2022-12-10  发布在  Swift
关注(0)|答案(1)|浏览(165)

我正在尝试使用SwiftUI制作一个类似于macOS Mail应用的分层侧栏,其中有父元素,如“All Sent”,然后是子元素,如单个邮箱,与典型的列表标题样式不同,父元素本身是可选的。Example of hiarchical sidebar, from the macOS mail app
我四处寻找解决方案,我能找到的唯一解决方案是父元素和子元素使用相同的swift类型,但我需要适用于不同类型的解决方案,例如,邮件服务器列表,它将文件夹列表作为子元素。

  1. struct MailServer {
  2. let id: UUID
  3. let name: String
  4. let folders: [MailServerFolder] = []
  5. }
  6. struct MailServerFolder {
  7. let id: UUID
  8. let name: String
  9. let items: [Message]
  10. }
  11. struct TestView: View {
  12. var body: some View {
  13. List(servers) { server in
  14. Section(content: {
  15. ForEach(server.folders) { folder in
  16. Text(channel.name)
  17. }
  18. }, header: {
  19. HStack {
  20. Text(server.name)
  21. }
  22. })
  23. }
  24. }
  25. }

请让我知道是否有办法在SwiftUI中实现这一点,或者是否需要基于AppKit的解决方案。

q3qa4bjr

q3qa4bjr1#

感谢user 1046037和Joakim Danielson的帮助!根据他们的建议,我选择了这个解决方案,效果很好

  1. struct ServerListView: View {
  2. @EnvironmentObject var store: Store
  3. @FetchRequest(
  4. entity: ServerEntry.entity(),
  5. sortDescriptors: []
  6. ) var serverEntries: FetchedResults<ServerEntry>
  7. var body: some View {
  8. List {
  9. OutlineGroup(Array(serverEntries) as [ServerEntry], id: \.id, children: \.children) { entry in
  10. Text(entry.title)
  11. }
  12. }
  13. }
  14. }
  15. protocol ListEntry: Identifiable {
  16. var id: ObjectIdentifier { get }
  17. var title: String { get }
  18. var children: [any ListEntry]? { get }
  19. }
  20. extension ServerEntry: ListEntry {
  21. var title: String {
  22. return self.name ?? ""
  23. }
  24. var children: [any ListEntry]? {
  25. return self.folders?.allObjects as! [FolderEntry]
  26. }
  27. }
  28. extension FolderEntry: ListEntry {
  29. var title: String {
  30. return self.name ?? ""
  31. }
  32. var children: [any ListEntry]? {
  33. return nil
  34. }
  35. }
展开查看全部

相关问题