I have a list of paths, for example a list parsed from the 'ls -R' stdout into an array, how can I create a very simple tree view list with that?
I am still learning swift, I can't figure out how to create the data structure necessary to populate a List view with children.
Moved this from the user's question to an answer:
Eventually I came up with this solution:
Create a Class for the items to display in the tree
class TreeItem: Identifiable{
let Id = UUID()
let Name: String
var isExpanded = false
var Children: [TreeItem] = [] //for subentries
init(name: String, children: [TreeItem] = []) {
self.Name = name
self.Children = children
}
}
Create a View for the tree
struct TreeItemView: View {
@State var item: TreeItem
@State private var topExpanded: Bool = false
var body: some View {
DisclosureGroup(
isExpanded: $topExpanded,
content: {
if !item.Children.isEmpty {
ForEach(item.Children) { child in
if (child.Children.isEmpty){
Text(child.Name))
}else{
TreeItemView(item: child)
}
}
}
},
label: {
Text(item.Name)
}
)
}
}
And here is the function returning a nested array of type TreeItem from a list of paths
func parsePaths(PathList: [String]) -> [TreeItem]{
let rootFolder = TreeItem(name: "root") //create startpoint
var pathList: [String] = PathList
pathList.removeAll { $0.isEmpty } //remove empty lines
for path in pathList{
let components = path.split(separator: "/").map(String.init) //split path in components by '/''
var currentFolder = rootFolder //set root folder
for component in components {
if let existingFolder = currentFolder.Children.first(where: { $0.Name == component }) {
currentFolder = existingFolder
} else {
let newFolder = TreeItem(name: component)
currentFolder.Children.append(newFolder)
currentFolder = newFolder
}
}
}
return rootFolder.Children
}
Here is the main view with some sample data:
struct ContentView: View {
@State var content:[TreeItem] = [] //initialize the content var
var body: some View {
Button("Show"){
content = parsePaths(PathList: [
"/FolderA/file.a",
"/FolderA/FolderAA/file.aa",
"/FolderB/FolderBB/FolderBBB/file.bbb",
"/FolderB/file.bbb",
"/FolderA/file.a1"
])
}
List{
ForEach(content, id: \.Id){item in
TreeItemView(item: item)
}
}
}
}