为什么 onAppear() 在 swiftUI 中放置在 NavigationView 内的元素上时会执行两次?(Xcode 12.0)

人气:966 发布:2022-10-16 标签: navigation swiftui xcode12 swiftui-navigationlink

问题描述

FirstView Appeared 被打印两次.一次是在视图首次加载时,一次是在选择 NavigationLink 时.

FirstView Appeared is printed twice. Once when the view first loads and again when the NavigationLink is selected.

import SwiftUI

struct FirstView: View {
    
    var body: some View {
        NavigationView{
            ZStack{
                Text("FirstView").onAppear(perform: {print("FirstView Appeared")})
                
                NavigationLink(destination: SecondView()) {
                    Text("Goto SecondView")
                }.offset(y: 50)
            }
        }
    }
}

struct SecondView: View {
    
    var body: some View {

        Text("SecondView").onAppear(perform: {print("SecondView Appeared")})
    }
}

在模拟器和个人设备上的 Xcode 12.0 beta 中运行上面的代码会在选择 NavigationLink 时产生以下输出:

Running the code above in Xcode 12.0 beta on both the simulator and a personal device produce the output below when the NavigationLink is selected:

FirstView Appeared
FirstView Appeared
SecondView Appeared

这是 onAppear() 预期行为的重复吗?

Is this duplication of onAppear() expected behavior?

如果是这样,在创建 firstview 并在返回 firstview 时加载一些数据的最佳实践是什么(因为 onAppear() 会尝试加载一些数据当离开 firstView)

If so, what best practices are there to load some data when firstview is created and then upon return to firstview (since onAppear() would attempt to load some data when navigating away from firstView)

推荐答案

我知道我参加聚会有点晚了,但万一其他人有同样的问题,只需将生命周期方法放在 之外NavigationView 为我工作.我正在模拟器上测试 - Xcode 12.2

I know i'm a little late to the party but in case any one else has the same problem, just placing the lifecycle methods outside of the NavigationView worked for me. I'm testing on Simulator - Xcode 12.2

struct fakeView1: View {
        
    func didAppear() {
        print("Appear")
    }

    func didDisappear() {
        print("Disppear")
    }

    var body: some View {
        NavigationView {
            VStack {
                Text("FAKE VIEW")
            }
        }
        .onAppear { didAppear() }
        .onDisappear { didDisappear() }
        .navigationBarTitle("Fake View", displayMode: .inline)
    }
}

963