Неожиданное поведение обновления представления - SwiftUI / Monterey

Следующий код вырезан из приложения, которое компилируется и работает под MacOS 11. Он показывает панель вкладок - щелчок по элементу выделяет его. Под панелью вкладок находится поле редактирования текста, в котором можно редактировать заголовок выбранной вкладки.

Есть 2 проблемы:

  1. Заголовок вкладки, отображаемый в редакторе заголовков, не совпадает по фазе с выбранной вкладкой.
  2. Независимо от того, какая вкладка выбрана, при редактировании заголовка всегда обновляется первая вкладка.

Я не уверен, что мне очень повезло, что этот код когда-либо работал в Big Sur, или возникла проблема с Монтереем. Я определенно не использую это как пример кода - я уверен, что есть более эффективные способы его реализации, но поинтересуйтесь, должно ли это работать.

      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
            }
    }
}

0 ответов

Другие вопросы по тегам