Using Swift5.3.2, iOS14.4.2, XCode12.4,
I am trying to make a PageView in SwiftUI, using iOS14's new PageTabViewStyle
for TabViews.
The pages shall be swappable smoothly from page to page.
It all works as long as I am not doing any kind of onChange
-action on selectedIndex
in any ways.
As soon as I do .onChange(of: selectedIndex) { newidx in ...}
then the swiping is laggy and no longer acceptable for usability.
But my app needs to keep track of the page-index and needs to perform code upon any index-change.
How can I detect swiping action in a PageView in SwiftUI ??
I realised that I always end up with swipe-gestures that are not smooth any more as soon as I use any kind of .onReceive()
or .onChange(of: )
with the selectedIndex
or any publisher thereof.
How can I overcome this problem and get a smooth swipe AND index-information ?
Here is my code:
struct CustomPageView: View {
@ObservedObject var myPageSelectionService = PageSelectionService()
@State private var contents = ["a","b","c"]
@State private var selectedIndex: Int = 0
var body: some View {
TabView(selection: $selectedIndex) {
ForEach(0..<contents.count, id:\.self) { i in
Text(contents[i]).tag(i)
}
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .automatic))
.onChange(of: selectedIndex) { newIndex in
print(newIndex)
}
}
}
I also tried a Publisher approach by replacing selectedIndex
by myService.selectedIndex. But no change - the app stalls when swiping and memory exceeds to the loops !
class MyService: ObservableObject {
@Published var selectedIndex = 0
}
What is there to do ?
Here is the entire App if curious:
import SwiftUI
enum MyState {
case waiting
case running
}
class AppState: ObservableObject {
@Published var myState: MyState = .running
}
class MyService: ObservableObject {
@Published var someServiceValue = 0
}
struct MainView: View {
@StateObject var appState = AppState()
@StateObject var myService = MyService()
var body: some View {
ParentView()
.environmentObject(appState)
.environmentObject(myService)
}
}
struct ParentView: View {
@EnvironmentObject var appState: AppState
@EnvironmentObject var myService: MyService
var body: some View {
NavigationView {
ZStack {
switch appState.myState {
case .waiting:
Text("Waiting")
case .running:
ChildView()
}
}
}
.navigationViewStyle(StackNavigationViewStyle())
.onChange(of: myService.someServiceValue) { newValue in
if newValue == 4 {
appState.myState = .waiting
}
}
}
}
struct ChildView: View {
@EnvironmentObject var myService: MyService
@State private var contents = ["img_team_ivo","img_team_beat","img_team_benny","img_team_irfan","img_team_jenny","img_team_lukas","img_team_sabrina","img_team_nici","img_team_pascal","img_team_patrick","img_team_silvan","img_team_stephan","img_team_christoph"]
@State private var selectedIndex: Int = 0
var body: some View {
ZStack {
ScrollView {
ZStack {
TabView(selection: $selectedIndex) {
ForEach(0..<contents.count, id:\.self) { index in
ZStack {
Image(contents[index])
.resizable()
.scaledToFit()
}
}
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .automatic))
}
}
}
.onChange(of: selectedIndex) { newIdx in
// !!!!!!!!!! app stalls - no more smooth swiping of Pages :(
myService.someServiceValue = newIdx
}
}
}