3

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. screenshot

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:

my code above in iOS simulator

2
  • Not sure what the issue is that you're asking for a solution - just tried both snippets of code from a blank SwiftUI project - both snippets work on each MacOS and iOS. Commented Apr 7, 2021 at 19:27
  • I wonder if it's something Xcode or OS version specific. I've narrowed things down a little. I will edit the post with new info: I find that if the first item in the top level of the list has no children, then it doesn't show it as a hierarchical list. Commented Apr 7, 2021 at 20:10

2 Answers 2

1

Your code works as expected on MacOS. All three Lists show the correct expandable children.

enter image description here

You could try restarting/updating XCode. One thing that is peculiar is that, the arrows appear on the right in the above screenshot while they appear on the left in post. Are there certain language/locale/formatting settings that you have added in your project and not included in the snippet above?

As an aside, the code as written has swapped the labels for children nil vs empty children. To clarify, tree1 is the one that has nil children while tree2 has empty children. The screenshot above runs OP's original unmodified code.

Sign up to request clarification or add additional context in comments.

2 Comments

I believe I have up-to-date MacOS and Xcode [11.2.3 & Version 12.4 (12D4e) respectively]
rohanphadte: you're right about nil and empty being switched. Thanks! And thanks for the suggestions. I believe I have up-to-date MacOS and Xcode [11.2.3 & Version 12.4 (12D4e) respectively] Neither re-starting Xcode nor cutting-and-pasting this code into a fresh Xcode project made any difference. As far as I know, I have not set any language, locale or formatting settings. Could this have something to do with Big Sur / Mac Catalyst?
0

I have a feeling that the nil / empty issue micgt be causing your problem. I have found that if the children are an empty array [] then the parent gets a little arrow... if the children are nil then there is no arrow.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.