I use TabView PageTabViewStyle with SwiftUI to display a pageview, when I swipe this TabView I find child view will Recall onAppear method Many times, Can someone tell me why?>
I've encountered similar problems due to bugs/features which have appeared with various 14.x releases. For example, on iOS 14.3 the code above prints this to the console at launch:
PageView :: body :: onReceive0 TextView :: body :: onReceive0 0 0 0 0 0 0 0 0 0 0 0
and this when swiping to index "1":
TextView :: body :: onReceive1 1 TextView :: body :: onReceive2 2 PageView :: body :: onReceive1 1 1 1 1 1 1
There appear to be two issues:
Here's a simplified example of a workaround that allows detection and debouncing of TabView page changes without using .onAppear.
import SwiftUI
struct ContentView: View {
@State private var currentView: Int = 0
var body: some View {
TabView(selection: $currentView) {
ChildView1(currentView: $currentView).tag(1)
ChildView2(currentView: $currentView).tag(2)
}
.tabViewStyle(PageTabViewStyle())
}
}
struct ChildView1: View {
@Binding var currentView: Int
@State private var debouncer = 0
let thisViewTag = 1
var body: some View {
Text("View 1")
.onChange(of: currentView, perform: { value in
if value == thisViewTag {
debouncer += 1
if debouncer == 1 {
print ("view 1 appeared")
}
} else {
debouncer = 0
}
})
}
}
struct ChildView2: View {
@Binding var currentView: Int
@State private var debouncer = 0
let thisViewTag = 2
var body: some View {
Text("View 2")
.onChange(of: currentView, perform: { value in
if value == thisViewTag {
debouncer += 1
if debouncer == 1 {
print ("view 2 appeared")
}
} else {
debouncer = 0
}
})
}
}