SwiftUI:如何从OutlineGroup获取选择?

时间:2020-06-24 01:36:55

标签: swiftui swiftui-outlinegroup

OutlineGroupNSOutlineView类似。 NSOutlineView支持单/多节点选择,我们可以通过在NSOutlineView上进行查询来获得它们。尽管NSOutlineView上的获得选择为O(n),但是如果视图跟踪选择并在适当的界面中提供选择,则可以将其优化为O(1)。

如何从OutlineGroup获取选择?特别是对于多个节点选择。我签出了the manual entry,但找不到关于选择的任何提及。我在这里想念什么?

2 个答案:

答案 0 :(得分:1)

文档看起来并不完整。在Xcode 12中使用直接SwiftUI自动生成的界面来查找更新。

特别是对于询问的OutlineGroup,有几个带有selection参数的构造函数,如下所示:

/// Creates a hierarchical list that computes its rows on demand from an
/// underlying collection of identifiable data, optionally allowing users to
/// select multiple rows.
///
/// - Parameters:
///   - data: The identifiable data for computing the list.
///   - selection: A binding to a set that identifies selected rows.
///   - rowContent: A view builder that creates the view for a single row of
///     the list.
@available(iOS 14.0, OSX 10.16, *)
@available(tvOS, unavailable)
@available(watchOS, unavailable)
public init<Data, RowContent>(_ data: Data, children: KeyPath<Data.Element, Data?>, 
    selection: Binding<Set<SelectionValue>>?, @ViewBuilder rowContent: @escaping (Data.Element) -> RowContent) where Content == OutlineGroup<Data, Data.Element.ID, HStack<RowContent>, HStack<RowContent>, DisclosureGroup<HStack<RowContent>, OutlineSubgroupChildren>>, Data : RandomAccessCollection, RowContent : View, Data.Element : Identifiable

答案 1 :(得分:1)

对于没有孩子的项目,您需要放置 NavigationLink / 按钮

这是基于Apple源代码的外观。

var body: some View {
    OutlineGroup(data, children: \.children) { item in
        Group {
            if item.children == nil {
                NavigationLink(
                    destination: Text("\(item.name)"),
                    label: {
                        Text ("\(item.description)")
                    })
            } else {
                Text ("\(item.description)")
            }
        }
    }
}

数据来自Apple example。有时链接会断开。因此,这是源代码:

struct FileItem: Hashable, Identifiable, CustomStringConvertible {
    var id: Self { self }
    var name: String
    var children: [FileItem]? = nil
    var description: String {
        switch (children) {
        case nil:
            return "? \(name)"
        case .some(let children):
            return children.count > 0 ? "? \(name)" : "? \(name)"
        }
    }
}

let data =
    FileItem(name: "users", children:
                [FileItem(name: "user1234", children:
                            [FileItem(name:"Photos", children:
                                        [FileItem(name: "photo001.jpg"),
                                         FileItem(name: "photo002.jpg")]),
                             FileItem(name:"Movies", children:
                                        [FileItem(name: "movie001.mp4")]),
                             FileItem(name:"Documents", children: [])
                            ]),
                 FileItem(name: "newuser", children:
                            [FileItem (name: "Documents", children: [])
                            ])
                ])