SwiftUI:如何从 OutlineGroup 中获取选择?
Posted
技术标签:
【中文标题】SwiftUI:如何从 OutlineGroup 中获取选择?【英文标题】:SwiftUI: How to get selections from OutlineGroup? 【发布时间】:2020-06-24 01:36:55 【问题描述】:OutlineGroup
类似于 NSOutlineView
。 NSOutlineView
支持单/多节点选择,可以通过NSOutlineView
查询获得。虽然在NSOutlineView
上获得选择是 O(n),但如果视图跟踪选择并在适当的界面中提供它们,这可以优化到 O(1)。
如何获取OutlineGroup
的选择?特别是对于多节点选择。我检查了the manual entry,但找不到任何关于选择的提及。我在这里错过了什么?
【问题讨论】:
从另一个问题回答。 ***.com/a/63786164/246776 【参考方案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
【讨论】:
我在自动生成的界面上找不到这个。你在 macOS 11(测试版)上检查过这个吗?我还在使用 macOS 10.x 看来OutlineGroup
需要是List
的内容。
@Eonil,不,我已经在 macOS 10.15.5 上安装了 Xcode 12b【参考方案2】:
您需要为没有子项的项目放置NavigationLink/Button。
这是基于 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: [])
])
])
【讨论】:
这如何使大纲组可选择? 没有子项的项目被包裹在 NaviationLink 中。 有人有解决这个问题的办法吗?请在此处发布。【参考方案3】:这是代码。
import SwiftUI
struct ContentView: View
@State var selection = Set<FileItem.ID>()
var body: some View
NavigationView
VStack
List(selection: $selection)
OutlineGroup(data, children: \.children) item in
Text("\(item.description)")
.onTapGesture
print(selection)
.listStyle(InsetGroupedListStyle())
.navigationTitle("Files")
//.toolbar EditButton()
.environment(\.editMode, .constant(.active))
.onTapGesture
// Walkaround: try how it works without `asyncAfter()`
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05, execute:
print(selection)
)
Text("\(selection.count) selections")
// Sample data:
struct FileItem: Hashable, Identifiable, CustomStringConvertible
var id: Self self
var name: String
var header: String?
var children: [FileItem]? = nil
var description: String
switch children
case nil:
return "? \(name)"
case .some(let children):
return children.isEmpty ? "? \(name)" : "? \(name)"
let data =
FileItem(name: "users", children:
[FileItem(name: "user1234", children:
[FileItem(name: "Photos", header: "Header 1", children:
[FileItem(name: "photo001.jpg", header: "Header 2"),
FileItem(name: "photo002.jpg")]),
FileItem(name: "Movies", children:
[FileItem(name: "movie001.mp4")]),
FileItem(name: "Documents", children: [])
]),
FileItem(name: "newuser", children:
[FileItem(name: "Documents", children: [])
])
])
struct ContentView_Previews: PreviewProvider
static var previews: some View
ContentView()
【讨论】:
以上是关于SwiftUI:如何从 OutlineGroup 中获取选择?的主要内容,如果未能解决你的问题,请参考以下文章