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

HELP -> Unexpected view update behaviour - SwiftUI / Monterey

Forums > SwiftUI

The following code is stripped out from an app that compiles and works under MacOS 11. It shows a tab bar - clicking on an item will highlight it. Under the tab bar is a text edit field where one can edit the title of the selected tab.

There are 2 issues:

  1. The tab title shown in the title editor is out of phase from the selected tab
  2. Irrespective of which tab item is selected, when the title is edited it always updates the first tab

I'm not sure if I was very lucky that this code ever worked under Big Sur, or if there is an issue with Monterey. I'm definitely not holding this up as example code - I'm sure there are better ways to implement it, but seek opinions on whether it should work.

import SwiftUI

class Document: ObservableObject {
    var tabs = [Tab(id: 0), Tab(id: 1)]
    @Published var activeTab: Int = 0
}

class Tab: ObservableObject, Identifiable {
    let id: Int
    @Published var title: String

    init(id: Int) {
        self.id = id
        self.title = "Tab \(id)"
    }
}

@main
struct Test: App {
    @StateObject var document: Document = Document()

    var body: some Scene {
        WindowGroup {
            ContentView()
                .padding()
                .environmentObject(document)
        }
    }
}

struct ContentView: View {
    @EnvironmentObject var document: Document

    var body: some View {
        TabBar()
        TabEditView(activeTab: document.tabs[document.activeTab])
    }
}

struct TabEditView: View {
    @EnvironmentObject var document: Document
    @ObservedObject var activeTab: Tab
    @State var title: String = ""

    init(activeTab: Tab) {
        print("CONSOLE - Init TabEditView for tab \(activeTab.id)")
        self.activeTab = activeTab
    }

    var body: some View {
        HStack {
            Text("Tab title:")
            TextField("Tab title:", text: $title, onCommit: { activeTab.title = title })
                .onAppear { title = activeTab.title }
                .onChange(of: document.activeTab) { _ in
                    print("CONSOLE - Updating TextField from tab \(activeTab.id)")
                    title = activeTab.title
                }
        }
    }
}

struct TabBar: View {
    @EnvironmentObject var document: Document

    var body: some View {
        HStack {
            ForEach(document.tabs, content: TabItem.init)
        }
    }
}

struct TabItem: View {
    @EnvironmentObject var document: Document
    @ObservedObject var tab: Tab

    init(_ tab : Tab) { self.tab = tab }

    var body: some View {
        Text(tab.title)
            .padding(2)
            .background(tab.id == document.activeTab ? .red : .clear)
            .cornerRadius(4)
            .onTapGesture {
                document.activeTab = tab.id
            }
    }
}

2      

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

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.