OutlineView in SwiftUI

I've got a MacOS app I'm converting to use SwiftUI. The UI uses NSOutlineView. Is there a SwiftUI equivalent for this?

Answered by pcr910303 in 613349022
It got released on the WWDC20 - there's now OutlineGroup
which allows code like this to be written:

Code Block swift
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: [])
])
])
OutlineGroup(data, children: \.children) { item in
Text ("\(item.description)")
}


AFAIK, you have to build it:

h ttps://twitter.com/schwa/status/1136498361110896641

I'm working through this same exercise at the moment...


So far I've found this one of the better articles to read - short and concise - https://dev.to/hugh_jeremy/adding-an-nstableview-to-a-swiftui-view-212p


Seems we need to create a wrapper with

NSViewControllerRepresentable


This is a work-in-progress for me...

It got released on the WWDC20 - there's now OutlineGroup
which allows code like this to be written:

Code Block swift
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: [])
])
])
OutlineGroup(data, children: \.children) { item in
Text ("\(item.description)")
}


10

I say don't bother. While the SwiftUI framework makes things that resemble an OutlineView, they fall very very far short of the flexibility offered by the Appkit and UIKit frameworks.

Notably, if you want users to be able to rearrange the items between parent / grandparent items, beware. You will not be able to do so in a way that users find intuitive, if at all, in pure SwiftUI.

I requested the ability to be able to drag items from one SwiftUI ForEach to another after WWDC22 revealed no improvements. (FB10064943). For me, this inhibits making a rock-solid sidebar, and while the TabView APIs this year get closer, they come with other design baggage I'm not sold on yet.

If you've already got an AppKit implementation, just drop that into SwiftUI land via the representable APIs. There are many places in SwiftUI that will get you 80% of the way to a great user experience, but the other 20% requires a fully bespoke solution that won't resemble the system provided UIs or support accessibility considerations.

Why it's taken over 2 years to add the ability to drag things between sections I'll never know. Probably deprioritized.

OutlineView in SwiftUI
 
 
Q