Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Outline View in SwiftUI

1024jp
November 02, 2024

Outline View in SwiftUI

macOS native symposium (https://macos-native.github.io) #10 登壇資料

複雑であるとともにMacらしいUIコントロールの一つであるアウトラインビューは近頃SwiftUIでも実装できそうですが、実際のところどうなんでしょうか?

1024jp

November 02, 2024
Tweet

More Decks by 1024jp

Other Decks in Programming

Transcript

  1. macOS native 0VUMJOF7JFXJO4XJGU6* ©2024 1024jp ࣗݾ঺հ CotEditor Gapplin Qli application

    works plain-text editor SVG viewer movie player macOS meet-up icon works @1024jp hobby macOS developer/designer
  2. macOS native 0VUMJOF7JFXJO4XJGU6* ©2024 1024jp 0VUMJOF7JFXJO$PU&EJUPS final class FileNode {

    enum Kind { case folder case general case archive case ... } let isDirectory: Bool private(set) var name: String private(set) var kind: Kind private(set) var isHidden: Bool ... private(set) var fileURL: URL private(set) weak var parent: FileNode? private var cachedChildren: [FileNode]? var children: [FileNode]? { if self.cachedChildren == nil, self.isDirectory { self.cachedChildren = try? self.readChildren() } return self.cachedChildren } }
  3. macOS native 0VUMJOF7JFXJO4XJGU6* ©2024 1024jp 0VUMJOF7JFXͷྺ࢙ Outline View Programming TopicsΑΓ

    https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/OutlineView/OutlineView.html#//apple_ref/doc/uid/10000023i
  4. macOS native 0VUMJOF7JFXJO4XJGU6* ©2024 1024jp 0VUMJOF7JFXͷྺ࢙ ZFBS 04 0VUMJOF7JFXؔ࿈ٕज़ ΄͔τϐοΫ

     0QFO4UFQ /45BCMF7JFX ʜ  .BD049 /40VUMJOF7JFX  0VUMJOF7JFX1SPHSBNNJOH5PQJDT  .BD049 $PDPB#JOEJOH  .BD049 /45SFF$POUSPMMFS  .BD049 /40VUMJOF7JFX%FMFHBUF %BUB4PVSDFϓϩτίϧԽ  .BD049 WJFXCBTFEUBCMF ʜ  NBD04 4XJGU6*  NBD04 4XJGU6*γϯάϧΧϥϜPVUMJOFWJFX  NBD04 4XJGU6*ϚϧνΧϥϜPVUMJOFWJFX SwiftUI࣌୅ʁʁ
  5. macOS native 0VUMJOF7JFXJO4XJGU6* ©2024 1024jp 0VUMJOF7JFXJO4XJGU6* List($items) { item in

    ForEach($items) { item in RowView(item: item) } } Table(of: Binding<Item>.self) { item in TableColumn("Name") { TextField(text: item.name, label: EmptyView.init) } } rows: { RecursiveTableRows(items: $items) } List($items, children: \.children) { item in TextField(text: item.name, label: EmptyView.init) } List { OutlineGroup($items, children: \.children) { item in TextField(text: item.name, label: EmptyView.init) } } Table(self.items, children: \.children) { item in TableColumn("Name", value: \.name) { Text(item.name) } } -JTUܥ 5BCMFܥ private struct RowView: View { @Binding var item: Item var body: some View { if let children = Binding<[Item]>($item.children) { DisclosureGroup(isExpanded: $item.isExpanded) { ForEach(children) { child in RowView(item: child) } } label: { TextField(text: $item.name, label: EmptyView.init) } } else { TextField(text: $item.name, label: EmptyView.init) } } } private struct RecursiveTableRows: TableRowContent { @Binding var items: [Item] var tableRowBody: some TableRowContent<Binding<Item>> { ForEach($items) { item in if let children = Binding(item.children) { DisclosureTableRow(item, isExpanded: item.isExpanded) { RecursiveTableRows(children) } } else { TableRow(item) } } } }
  6. macOS native 0VUMJOF7JFXJO4XJGU6* ©2024 1024jp 0VUMJOF7JFXJO4XJGU6* NSOutlineView List Table children

    disclosure OutlineGroup children disclosure available macOS 10.0 macOS 12 macOS 12 macOS 11 macOS 14 macOS 14 ηΫγϣϯϔομ Section ✔︎ × ✔︎ ✔︎ × ✔︎ ฤू @Binding ✔︎ ✔︎ ✔︎ ✔︎ × ✔︎ ։ด੍ޚ isExpanded ✔︎ × ✔︎ × × ✔︎ D&Dιʔτ ✔︎ × △ × × △ ΧϥϜΧελϚΠζ columnCustomization ✔︎ ✔︎ ✔︎ ΧϥϜιʔτ sortOrder ✔︎ ✔︎ ✔︎ ʢཁखಈΩϟετʣ
  7. macOS native 0VUMJOF7JFXJO4XJGU6* ©2024 1024jp %SBH%SPQ "1* ڍಈ ෆ౎߹ ForEach()

    { ... }.onMove(perform:) ҠಈݩͷSPXͷIndexSet͕ಘΒΕΔ r ಉҰ֊૚಺ͷҠಈʹ͔͠࢖͑ͳ͍ onDrop(of:delegate:) %FMFHBUFͰΠϕϯτผͷॲཧΛ ࡉ੍͔͘ޚͰ͖Δ ʢNSTableViewDelegateʹ͍ۙʣ r 伱ؒʹೖΕΒΕͳ͍ r ෳ਺߲໨͕υϩοϓ͞ΕΔ͜ͱΛߟྀ͍ͯ͠ͳ͍ onDrop(of:perform:) onInsert(of:perform:) [NSItemProvider]͕ಘΒΕΔ [NSItemProvider]ͱIndex͕ ಘΒΕΔ r υϩοϓͰඞͣ ➕ϚʔΫ͕ग़Δ  dropDestination( for:action:) ࣗ਎ͷҠಈ [any Transferable]͕ಘΒΕΔ 成功事例待ってます!! r ԿΕʹͤΑɺʮΰϛശ΁υϩοϓʯͳΜ͔͕͕Ͱ͖ͳ͍