今天水群看到有群友问问题:

问题

目前他是用onappear来实现的。大致的例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
struct ContentView: View {
var body: some View {
NavigationView {
NavigationLink(destination: DetailView()) {
Text("跳转一个页面")
}
}
.onAppear {
print("我来啦")
}
}
}

如何每次到这个ContentView的时候都触发print("我来啦")

解决方案

其实这就是跟swiftui的机制有关,当你访问到DetailView()的时候,其实只是在NavigationView中显示了一个视图。

无论你是否跳转到子页面,Navigationview都始终显示,不会触发onAppearonDisappear

所以只需要在一个会发生变动的元素上标记onAppear属性即可。

所以我们更改一下onAppear描述的对象:

1
2
3
4
5
6
7
8
9
10
11
12
struct ContentView: View {
var body: some View {
NavigationView {
NavigationLink(destination: DetailView()) {
Text("跳转一个页面")
}
.onAppear {
print("我来啦")
}
}
}
}

我们将onAppear描述对象改为不会始终显示的NavigationLink视图,因为跳转子页面的时候NavigationLink被遮住不可见。所以可以触发onDisappear。当返回时同理,可以触发onAppear

Swiftui是一个比较看重代码顺序和位置的框架,当遇到问题的时候可以向这方面分析一下。

扩展方案

当页面元素比较多的时候可以放在NavigationView的下一级。或者自己套一个层级。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
struct ContentView: View {
var body: some View {
NavigationView {
List {
ForEach(0 ..< 200) {i in
NavigationLink(destination: DetailView()) {
Text("跳转一个页面")
}
.onAppear {
print("我来啦\(i)")
}
.onDisappear {
print("我走啦\(i)")
}
}

}
.onAppear {
print("我们一起来啦")
}

}
}
}

struct DetailView: View {
var body: some View {
Text("Detail View")
}
}