SwiftUI 强制子视图重绘

Posted

技术标签:

【中文标题】SwiftUI 强制子视图重绘【英文标题】:SwiftUI force child view to redraw 【发布时间】:2020-12-09 12:37:12 【问题描述】:

我有一个带有子视图的模态视图,它本身有另一个子视图。当我旋转设备时,需要重绘第一个子视图以将新的 GeometricReader 数据传递给最后一个子视图。

我正在通过视图模型中的通知中心检测旋转

    @objc func updateView(_ : Notification) 
        self.refresh.toggle()
        self.objectWillChange.send()
        

视图模型有两个属性。

        @Published var objectWillChange = ObservableObjectPublisher()
        @Published var refresh: Bool

在视图中我有一个@observedObject vm,但是当 vm 更改时,视图不会重绘。对于一些需要重新对齐的线条图,第一个孩子需要重绘以将其大小发送给第二个孩子。

[编辑]

struct StackView: View 
@ObservedObject var vm = ViewModel()

var body: some View 
    
    Color.white
    VStack 
        Spacer()
        VStack 
            Text("Hello StackView")
            View2()
        
    



extension StackView 
final class ViewModel: ObservableObject 
    
    init() 
        NotificationCenter.default.addObserver(self, selector: #selector(updateView(_:)), name: UIDevice.orientationDidChangeNotification, object: nil)
    
    
    deinit 
        NotificationCenter.default.removeObserver(self, name: UIDevice.orientationDidChangeNotification, object: nil)
    
    
    @objc func updateView(_ notification: Notification) 
        self.objectWillChange.send()
    



struct View2: View 

var body: some View 
    Text("Hello view 2")
        .overlay(GeometryReader  geo in
            Color.clear
                .onAppear 
                    print(geo.frame(in: .global))
                
        )


【问题讨论】:

我根本看不出该通知使用的任何原因。目标是什么 - 布局会在旋转时自动更新? 如你所说,旋转得到照顾,但我需要让 view2 重绘。该视图上有连接到图像的线,当它们由于旋转而移动时,它们需要获取更新的值。 【参考方案1】:
    @Published var objectWillChange = ObservableObjectPublisher()

删除此行。 ObservableObject 具有 objectWillChange 属性的默认发布者实现,所以只需使用它,就像

@objc func updateView(_ : Notification) 
   self.objectWillChange.send()

如果您对var refresh: Bool 没有特殊含义,则也不需要。

【讨论】:

它仍然不打球。视图 A 不会重绘(我应该会看到 GeometryReader 打印一些值),这意味着视图 B 也不会。 (同样有 GeometryReaders 应该打印值) 你能提供一些最小的可重现代码吗?我认为原始问题中遗漏了一些东西。顺便说一句,GeometryReader 不需要强制更新,它会自动更改尺寸,因此如果您不进行任何硬编码,那么内部部件应该无需干预即可更新。这看起来像是其他代码中某处的原因。 View2 中有一些硬编码的形状从框架中获取值,因此我需要重新绘制它以更新这些值。

以上是关于SwiftUI 强制子视图重绘的主要内容,如果未能解决你的问题,请参考以下文章

使自定义 SwiftUI 视图适应内置修饰符

SwiftUI:ObservableObject 在重绘时不会保持其状态

如何在 SwiftUI 中触发状态更改/重绘切换更改

SwiftUI List 重绘已呈现工作表的内容

有没有办法强制 SwiftUI 中的横向模式仅用于某些视图?

SwiftUI:如何更改子视图?