Reputation: 79
I have implemented a tree view representing different types of objects. Details for these objects should be displayed in a tabbed table view. If I do select an object in the tree, the details of this object will be displayed in the table. This works as expected, as long as i do select objects on different hierarchy levels. But if I select objects on the same hierarchy level the table view is not updated.
I assume I do make a mistake in my table views so they are not always updates on selection change.
import SwiftUI
struct ContentView: View {
@State var navSelection = Set<Tree<String>>()
var body: some View {
NavigationSplitView {
List(treeNodes, id: \.value, children: \.children, selection: $navSelection) { tree in
NavigationLink(value: tree) {
TreeView(node: tree)
}
}
.contextMenu(forSelectionType: Tree<String>.self) { nodes in
if nodes.first!.value == "House 1" {
Button("House 1 seleced") {}
} else {
Button("No node or more than 1 selected") {}
}
}
.listStyle(SidebarListStyle())
} detail: {
TabView {
if let tab = navSelection.first {
if tab.objectRef is Root {
Tab("Houses", image: "Haus") {
// swiftlint: disable force_cast
HousesView(data: (tab.objectRef as! Root).houses)
}
} else if tab.objectRef is House {
Tab("Apartments", image: "Wohnung") {
ApartmentView(data: (tab.objectRef as! House).apartments)
// swiftlint: enable force_cast
}
}
}
Tab("Info", systemImage: "pencil") {
Text("navSelection: \(navSelection.first?.value)")
}
}
}
}
}
struct ApartmentView: View {
@State var data: [Apartment]
var body: some View {
Table(data) {
TableColumn("Floor", value: \.floor)
TableColumn("Rooms", value: \.rooms)
}
}
}
struct HousesView: View {
@State var data: [House]
var body: some View {
Table(data) {
TableColumn("Name", value: \.name )
TableColumn("Addresse", value: \.address)
}
}
}
class Tree<String: Hashable>: Hashable, ObservableObject {
var value: String
var icon: String?
var objectRef: AnyObject
var children: [Tree]?
init(value: String, icon: String? = nil, objRef: AnyObject, children: [Tree]? = nil) {
self.value = value
self.icon = icon
self.objectRef = objRef
self.children = children
}
static func == (lhs: Tree<String>, rhs: Tree<String>) -> Bool {
return lhs.value == rhs.value
}
func hash(into hasher: inout Hasher) {
hasher.combine(value)
}
}
// MARK: - init demo data
class Root {
var name: String
var someData: String
var houses: [House]
init(name: String, someData: String, houses: [House] = []) {
self.name = name
self.someData = someData
self.houses = houses
}
}
class House: Identifiable {
var name: String
var address: String
var apartments: [Apartment]
init(name: String, address: String, apartments: [Apartment] = []) {
self.name = name
self.address = address
self.apartments = apartments
}
}
class Apartment: Identifiable {
var id = UUID()
var floor: String
var rooms: String
init(floor: String, rooms: String) {
self.floor = floor
self.rooms = rooms
}
}
var root = Root(name: "Root", someData: "some test data", houses: houses)
var houses = [House(name: "House 1", address: "street address of house 1", apartments: apartments1),
House(name: "House 2", address: "street address of house 2"),
House(name: "House 3", address: "street address of house 3", apartments: apartments2)]
var apartments1 = [Apartment(floor: "1. left", rooms: "3"), Apartment(floor: "1. right", rooms: "1")]
var apartments2 = [Apartment(floor: "2. left", rooms: "2"), Apartment(floor: "2. right", rooms: "2")]
/// example data using string values
let treeNodes: [Tree<String>] = [
.init(
value: "Root", icon: "Block",
objRef: root, children: [
.init(value: "House 1", icon: "Haus", objRef: houses[0],
children: [
.init(value: "Apartments1 1", icon: "Wohnung", objRef: apartments1[0]),
.init(value: "Apartments1 2", icon: "Wohnung", objRef: apartments1[1])
]
),
.init(value: "House 2", icon: "Haus", objRef: houses[1]),
.init(value: "House 3", icon: "Haus", objRef: houses[2],
children: [
.init(value: "Apartments2 1", icon: "Wohnung", objRef: apartments2[0]),
.init(value: "Apartments2 2", icon: "Wohnung", objRef: apartments2[1])
]
)
]
)
]
Hopefully someone can help me change my example in a way that every selection change will update the tables.
Upvotes: 0
Views: 38