Navigationbar- / Toolbar Button not working reliable when @State variable refresh the view with a high frequency

前端 未结 1 1980
猫巷女王i
猫巷女王i 2021-01-03 01:08

I noticed that Navigationbar- / Toolbar Buttons are not working properly when there is at least one @State variable refreshing the View very often.

I created a simple

相关标签:
1条回答
  • 2021-01-03 01:44

    The number state in provided variant refreshes entire view, that is a result of issue, and not very optimal for UI.

    The solution for navigation bar, and in general good style, is to separate refreshing part into standalone view, so SwiftUI rendering engine rebuild only it.

    Tested with Xcode 12b3 / iOS 14

    struct TestOftenUpdate: View {
    
        @State private var showModal = false
    
        var body: some View {
    
            NavigationView {
                VStack {
                    QuickTimerView()
                    Button(action: { showModal.toggle() }, label: {
                        Text("Open Modal")
                    })
                }
                .navigationBarTitle("Home", displayMode: .inline)
                .navigationBarItems(leading:
                                        Button(action: {
                                            showModal.toggle()
                                        }, label: {
                                            Text("Open Modal")
                                        }))
    
                .toolbar {
                    ToolbarItem(placement: .bottomBar) {
                        Button(action: {
                            showModal.toggle()
                        }, label: {
                            Text("Open Modal")
                        })
                    }
                }
            }
    
            .sheet(isPresented: $showModal, content: {
                Text("Hello, World!")
            })
    
        }
    }
    
    struct QuickTimerView: View {
        @State private var number = 0
    
        var body: some View {
            VStack {
                Text("Count \(number)")
                Button(action: startTimer, label: {
                    Text("Start Timer")
                })
            }
        }
    
        func startTimer() {
            Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { (_) in
                number += 1
            }
        }
    
    }
    

    With toolbar is different issue - it does not work after first sheet open even without timer view, and here is why

    as it is seen the button layout has corrupted and outside of toolbar area, that is why hit testing fails - and this is Apple defect that should be reported.

    Workaround 1:

    Place toolbar outside navigation view (visually toolbar is smaller, but sometimes might be appropriate, because button works)

        NavigationView {
           // ... other code
        }
        .toolbar {
            ToolbarItem(placement: .bottomBar) {
                Button(action: {
                    showModal.toggle()
                }, label: {
                    Text("Open Modal")
                })
            }
        }
    
    0 讨论(0)
提交回复
热议问题