SwiftUI 2 .onChange() 中的选取器不会更改 UINavigationBar.appearance()

Posted

技术标签:

【中文标题】SwiftUI 2 .onChange() 中的选取器不会更改 UINavigationBar.appearance()【英文标题】:Picker in SwiftUI 2 .onChange() does not change UINavigationBar.appearance() 【发布时间】:2020-09-27 00:00:59 【问题描述】:

所以这是一个奇怪的...在 SwiftUI 2 启动之前,我在视图的 init() 中设置 UINavigationBar.appearance() 如下:

init(selectedStyle: Binding<Int>) 
        _selectedStyle = selectedStyle
        if self.selectedStyle == 1 
            UINavigationBar.appearance().backgroundColor = UIColor.init(displayP3Red: 7/255, green: 7/255, blue: 7/255, alpha: 1)
            UISegmentedControl.appearance().backgroundColor = .black
            UINavigationBar.appearance().titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
            UISegmentedControl.appearance().setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.black], for: UIControl.State.selected)
            UISegmentedControl.appearance().selectedSegmentTintColor = .white
            UISegmentedControl.appearance().setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.white], for: UIControl.State.normal)
         else 
            UINavigationBar.appearance().backgroundColor = .white
            UISegmentedControl.appearance().backgroundColor = .white
            UISegmentedControl.appearance().selectedSegmentTintColor = .white
            UINavigationBar.appearance().titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.black]
            UISegmentedControl.appearance().setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.black], for: UIControl.State.selected)
            UISegmentedControl.appearance().setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.black], for: UIControl.State.normal)
        
    

在 SwiftUI 1 中,视图将再次初始化,因此导航栏的新外观将正确更新。因为 init() 函数会再次运行。我试图将相同的代码放在附加到 Picker 的 onChange() 中,但由于某种原因它不起作用:

Picker(selection: $selectedStyle, label: Text("")) 
    ForEach(0 ..< 3) 
        Text([$0])
    

.pickerStyle(SegmentedPickerStyle())
.onChange(of: selectedStyle, perform:  change in
    if self.selectedStyle == 1 
            UINavigationBar.appearance().backgroundColor = UIColor.init(displayP3Red: 7/255, green: 7/255, blue: 7/255, alpha: 1)
            UISegmentedControl.appearance().backgroundColor = .black
            UINavigationBar.appearance().titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
            UISegmentedControl.appearance().setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.black], for: UIControl.State.selected)
            UISegmentedControl.appearance().selectedSegmentTintColor = .white
            UISegmentedControl.appearance().setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.white], for: UIControl.State.normal)
         else 
            UINavigationBar.appearance().backgroundColor = .white
            UISegmentedControl.appearance().backgroundColor = .white
            UISegmentedControl.appearance().selectedSegmentTintColor = .white
            UINavigationBar.appearance().titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.black]
            UISegmentedControl.appearance().setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.black], for: UIControl.State.selected)
            UISegmentedControl.appearance().setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.black], for: UIControl.State.normal)
        
    )

【问题讨论】:

【参考方案1】:

appearance 对 UI 元素产生影响 设置相应的外观。所以你需要重新创建所有依赖的 UI。

可能的方法如下 - 假设您在 ContentView 的根目录中有 NavigationView,您可以通过

重新创建它(以及所有子视图)
var body: some View 
   NavigationView 

     // .. content here

   .id(selectedStyle)       // << here !!

【讨论】:

我该如何重新创建它呢?另外,为了清楚起见——.id 属性只是给出了对该特定代码块的引用,对吧? 是的,但是当 id 改变时视图会被重新创建,因为它应该已经是不同的视图了。

以上是关于SwiftUI 2 .onChange() 中的选取器不会更改 UINavigationBar.appearance()的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI:onChange(of:scenePhase)没有触发

SwiftUI 无法添加 onChange 事件

在 SwiftUI 视图中结合 onChange 和 onAppear 事件?

SwiftUI onChange(of: ...) 更新 StateObject

SwiftUI 中的可选状态或绑定

如何在外部类中的事件后更新 SwiftUI 按钮?