@State 变量高频刷新视图时,导航栏/工具栏按钮无法可靠工作

2023-11-26

我注意到,当至少有一个 @State 变量经常刷新视图时,导航栏/工具栏按钮无法正常工作。

我创建了一个简单的应用程序来测试它。

在下面的代码示例中,您有 3 个选项来触发模式表。主视图中有一个按钮,工具栏中有一个按钮,导航栏中有一个按钮。

当我的计时器没有更新“数字”时,所有 3 个按钮都可以正常工作。当我启动计时器时,它将每 0.1 秒刷新一次视图,只有主视图中的按钮每次都会起作用。工具栏/导航栏中的按钮大多数时候不起作用。 (计时器的时间间隔越短,按钮起作用的次数就越少)

import SwiftUI

struct ContentView: View {

    @State private var number = 0
    @State private var showModal = false

    func startTimer() {
        Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { (_) in
            number += 1
        }
    }

    var body: some View {

        NavigationView {
            VStack {
                Text("Count \(number)")
                Button(action: startTimer, label: {
                    Text("Start Timer")
                })

                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!")
        })

    }
}

有谁知道是否有办法让这两个按钮正常工作?

Xcode 12 beta 5 和 Xcode Xcode 11.6 会出现此问题(没有工具栏,因为它在那里不可用)


The number提供的变体中的状态会刷新整个视图,这是问题的结果,对于 UI 来说并不是最佳选择。

导航栏的解决方案(一般来说良好的风格)是将刷新部分分离到独立视图中,因此 SwiftUI 渲染引擎仅重建它。

使用 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是不同的问题 - 即使没有计时器视图,在打开第一张纸后它也不起作用,这就是为什么

demo

因为可以看到按钮布局已损坏并且位于工具栏区域之外,这就是点击测试失败的原因 - 这是应该报告的 Apple 缺陷。

解决方法1:

将工具栏放置在导航视图之外(视觉上工具栏较小,但有时可能是合适的,因为按钮可以工作)

    NavigationView {
       // ... other code
    }
    .toolbar {
        ToolbarItem(placement: .bottomBar) {
            Button(action: {
                showModal.toggle()
            }, label: {
                Text("Open Modal")
            })
        }
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

@State 变量高频刷新视图时,导航栏/工具栏按钮无法可靠工作 的相关文章

随机推荐