UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SOLVED: display 2 tabViews getting data from a Tree

Forums > SwiftUI

I watched the video about the node structures by Paul https://www.hackingwithswift.com/plus/data-structures/trees and I wanted to display the family tree using TabViews:

The user swipes on the first TabView (the children ) and the TabView below displays the children of the children (grandchildren) The code is below. I cannot make it to work! It seems trivial but the second tabview gets updated showing the dots.. but not refreshing the array of grandchildren. How would you do that?

import SwiftUI

struct Node<String> {
    var id = UUID()
    var string: String
    private(set) var children: [Node]

    mutating func add(child: Node) {
        children.append(child)
    }
    init(_ value: String) {
        self.string = value
        children = []
    }

    init(_ value: String, children: [Node]) {
        self.string = value
        self.children = children
    }
}

struct ContentView: View {

    var root: Node<String>

    init() {
        var child1 = Node("child1")
        let grandChild = Node("grandChild")
        child1.add(child: grandChild)

        var child2 = Node("child2")
        let grandChild1 = Node("grandChild1")
        let grandChild2 = Node("grandChild2")
        child2.add(child: grandChild1)
        child2.add(child: grandChild2)

        var root = Node("Root")
        root.add(child: child1)
        root.add(child: child2)
        //print(root)
        self.root = root
    }

    @State var selection = 0

    var body: some View {
        VStack {
            TabView(selection: $selection) {
                ForEach(root.children.indices) { index in
                    Text(root.children[index].string)
                }.tag(selection)
            }.tabViewStyle(PageTabViewStyle())

            TabView {
                ForEach(root.children[selection].children, id: \.id) { child in
                    Text(child.string)
                }
            }.tabViewStyle(PageTabViewStyle())
        }.background(Color.green)
    }
}

3      

Change your second TabView to this and it will work:

            TabView {
                ForEach(root.children[selection].children, id: \.id) { child in
                    Text(child.string)
                }
            }
            .id(Int.random(in: 0..<Int.max))
            .tabViewStyle(PageTabViewStyle())

4      

@Roosterboy Thank you so much!! I spent hours on this!!!

.id(Int.random(in: 0..<Int.max))

So this is resetting and reloading my view. Nice hack! 😹

3      

In thinking about it, though, it might be better to use a @State property for the view id and increment it instead of assigning a random number. There's always the chance—however slim—that a random number could be repeated twice in a row and then the View wouldn't reload.

4      

True, good idea... It would look cleaner. But how to increment that state property. I tried using $selection of the previous TabView as id(selection) and it did not work (?) however at that time I had still various other small bugs in my code, so will check it out again. Thanks!

3      

You could attach an onChange handler to the first TabView:

    @State private var viewID = 0

    var body: some View {
        VStack {
            TabView(selection: $selection) {
                ForEach(root.children.indices) { index in
                    Text(root.children[index].string)
                }.tag(selection)
            }.tabViewStyle(PageTabViewStyle())
            .onChange(of: selection) { _ in
                viewID += 1
            }

       ...

But using the selection value as the ID seems to work as well.

4      

BUILD THE ULTIMATE PORTFOLIO APP Most Swift tutorials help you solve one specific problem, but in my Ultimate Portfolio App series I show you how to get all the best practices into a single app: architecture, testing, performance, accessibility, localization, project organization, and so much more, all while building a SwiftUI app that works on iOS, macOS and watchOS.

Get it on Hacking with Swift+

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.