Update
I'm trying to use the hierarchical List view in SwiftUI (List( tree, children:)). I find that if the first list element has no children, only the top level of the hierarchy is shown. This looks like a bug in SwiftUI to me. I wonder if anyone knows of a good fix.
[This is a better version of my question, using the same struct type and same array elements]
@main
struct bug_reportApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct FileItem: Hashable, Identifiable, CustomStringConvertible {
var id: Self { self }
var name: String
var children: [FileItem]? = nil
var description: String {
return name
}
}
let tree0: [FileItem] = [
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")
]),
FileItem(name: "newuser", children:
[FileItem(name: "Documents", children: [])
])
]),
FileItem(name: "private", children: nil)
]
let tree1 = [tree0[1], tree0[0]]
let tree2 = [FileItem(name: "private", children: []), tree0[0]]
struct ContentView: View {
var body: some View {
HStack{
VStack{
Text("Works").font(.headline)
List(tree0, children: \.children) { item in
Text(item.description)
}
}
VStack{
Text("First element has empty .children").font(.headline)
List(tree2, children: \.children) { item in
Text(item.description)
}
}
VStack{
Text("First element has nil .children").font(.headline)
List(tree1, children: \.children) { item in
Text(item.description)
}
}
}
}
}
Here an annotated screenshot, highlighting where the missing tree expansion arrow is/should be.

Original question
I'm trying to use the hierarchical List view in SwiftUI (List( tree, children:)).
I can't see why my simple example here displays only the 3 top-level 3 items, with no little arrow to expand the sub-list under list element #2.
I can cut and paste very similar looking examples (into the same project, same file) and they do work... but I can't spot the difference!
My code that doesn't work:
import SwiftUI
struct TreeIndexNode: Hashable, Identifiable, CustomStringConvertible {
var id: Int
var children: [TreeIndexNode]? = nil
var description: String {
return String("\(id)")
}
}
struct ContentView: View {
let tree: [TreeIndexNode] = [ TreeIndexNode(id: 1), TreeIndexNode(id: 2, children: [
TreeIndexNode(id: 3),
TreeIndexNode(id: 4),
]),
TreeIndexNode(id: 8),
]
var body: some View {
List( tree, children: \.children) { row in
Text(row.description)
}
}
}
but if I switch it to this example from Apple Developer pages, it works as expected:
struct ContentView: View {
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.isEmpty ? "📂 \(name)" : "📁 \(name)"
}
}
}
let fileHierarchyData: [FileItem] = [
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: [])
])
]),
FileItem(name: "private", children: nil)
]
var body: some View {
List(fileHierarchyData, children: \.children) { item in
Text(item.description)
}
}
}
I started from the Xcode 12.4 "Multiplatform" project template. Here's what it looks like on MacOS:
Screen shot of non-working MacOS build of my code above
When I build for iOS, it does work as expected:
