3

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
        }
    }
}
iKK
  • 6,394
  • 10
  • 58
  • 131

0 Answers0