Ios 为什么GeometryReader的主体要评估两次?也是第一次,维度为零?

Ios 为什么GeometryReader的主体要评估两次?也是第一次,维度为零?,ios,swift,swiftui,navigationview,geometryreader,Ios,Swift,Swiftui,Navigationview,Geometryreader,我有一个GeometryReader嵌套在NavigationView中。在GeometryReader中,我使用GeometryProxy提供的尺寸和if语句。在我的项目中,我无意中发现了这样一个事实:GeometryReader中的内容被评估了两次,提供的维度第一次是宽度0和高度0。此外,if案例中内容的onAppear()方法被调用两次,这会导致更多问题 有人能解释一下这种行为吗?这样我就可以改进我的代码了 我举了一个简单的例子来说明这个问题: import SwiftUI struct

我有一个GeometryReader嵌套在NavigationView中。在GeometryReader中,我使用GeometryProxy提供的尺寸和if语句。在我的项目中,我无意中发现了这样一个事实:GeometryReader中的内容被评估了两次,提供的维度第一次是宽度0和高度0。此外,if案例中内容的onAppear()方法被调用两次,这会导致更多问题

有人能解释一下这种行为吗?这样我就可以改进我的代码了

我举了一个简单的例子来说明这个问题:

import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationView() {
            NavigationLink(destination: SecondView()) {
                Text("Click me!")
            }
        }
        .navigationViewStyle(StackNavigationViewStyle())
    }
}

struct SecondView: View {
    private func showHorizontal(_ w: CGFloat, _ h: CGFloat) -> Bool {
        print("Dimensions \(w), \(h)")
        return (w > h)
    }
    
    var body: some View {
        GeometryReader { proxy in
            if self.showHorizontal(proxy.size.width, proxy.size.height) {
                Text("Landscape")
                .onAppear() {
                    print("Landscape appeared")
                }
            } else {
                Text("Portrait")
                .onAppear() {
                    print("Portrait appeared")
                }
            }
        }
        .onAppear() {
            print("GeometryReader appeared")
        }
    }
}
在横向方向的iPad上,我获得以下控制台输出:

Dimensions 0.0, 0.0
Dimensions 1194.0, 688.0
GeometryReader appeared
Landscape appeared
Landscape appeared

GeometryReader
正在更新其几何结构的变化,这是有意义的。在if子句中,您正在为每个计算创建一个新的
Text
视图。您看到的是每一个的
外观

if self.showHorizontal(proxy.size.width, proxy.size.height) {
         Text("Landscape")
         .onAppear() {
             print("Landscape appeared")
     }
}
如果出于某种原因需要文本保持不变,可以使用为其分配一个id,如下所示:

if self.showHorizontal(proxy.size.width, proxy.size.height) {
         Text("Landscape")
         .id("fixed id")
         .onAppear() {
             print("Landscape appeared")
     }
}

我尝试在12.4(12D4e)中运行OP的示例代码,但没有得到双重求值行为。发布时,我得到:

尺寸1024.01366.0
尺寸1024.0、1220.0
GeometryReader出现了
肖像出现了
旋转4次(整圈):

尺寸1366.0878.0
景观出现
尺寸1366.0898.0
尺寸1024.0、1220.0
肖像出现了
尺寸1366.0878.0
景观出现
尺寸1366.0898.0
尺寸1024.0、1220.0
肖像出现了
硬编码一个ID,比如
.ID(“景观”)
,不会影响行为,并从上面得到相同的打印语句

为了避免在每次旋转时打印“纵向/横向显示”,我将if语句中的
Text()
分解为:

GeometryReader{中的代理
让text=self.showHorizontal(proxy.size.width,proxy.size.height)?“Lanscape”:“纵向”
文本(“\(文本)”)
//.id(text)//如果希望看到每次旋转都显示“方向”,请取消注释
.onAppear(){
打印(\(文本)出现)
}
}
.onAppear(){
打印(“GeometryReader出现”)
}
现在发射,一整圈旋转产生:

尺寸1024.01220.0
肖像出现了
GeometryReader出现了
尺寸1366.0878.0
尺寸1366.0898.0
尺寸1024.0、1220.0
尺寸1366.0878.0
尺寸1366.0898.0
尺寸1024.0、1220.0

看起来它会根据几何体的变化进行更新,这很有意义。