It doesn't handle big data, that's why it's TabView, not PageView. Its purpose is display tabs as page style, not display pages.
If you insist to use TabView for big data, stop using @Published
for page index or it will reload all child views (7000 in your example) and cause the lag
You can test it out on your preview with my example code
struct TestView: View {
@StateObject var viewModel = ViewModel()
@State var index = 0
@State var usePublished = false
var data = 0..<1000
var body: some View {
VStack(spacing: 40) {
if usePublished {
TabView(selection: $viewModel.index) {
ForEach(data, id:\.self) { i in
TestContentView(i).tag(i)
}
}
} else {
TabView(selection: $index) {
ForEach(data, id:\.self) { i in
TestContentView(i).tag(i)
}
}
}
Toggle("using @Published", isOn: $usePublished)
.fixedSize()
}.tabViewStyle(.page(indexDisplayMode: .always))
}
}
struct TestContentView: View {
static var initCount = 0
@State var initCount = 0
var value: Int
init(_ value: Int) { self.value = value ; Self.initCount += 1 }
var body: some View {
VStack(spacing: 40) {
Spacer()
Text("page \(value)")
Divider()
Text("init count : \(initCount)")
}.onReceive(Timer.publish(every: 0.1, on: .main, in: .default).autoconnect()) { _ in
initCount = Self.initCount
}
}
}
extension TestView {
class ViewModel: ObservableObject {
@Published var index = 0
}
}
struct TestOtherTestViews_Previews: PreviewProvider {
static var previews: some View {
TestView()
}
}
No new init when changing page with @State

1000 new inits each time changing page with @Published
