Search code examples
swiftswiftuiswiftui-tabview

SwiftUI TabView how can I load more data on 2nd tab click


I am working with TabView and would like to add more data when a user clicks for the 2nd time on the same tab item . I have been looking at other examples such as this SwiftUI TabView On Click Action however I have not been able to get it to work . I have a simple example below (full code) . Basically if the tag is already on MainView and the user clicks it again I want to hit the print("Update get more data") code . I have used the OnReceive method however that does not work if clicked more than 1 time in the same tab . I have also tried to use onTapGesture outside of the TabView but do not seem to bind any suggestions would be great since I am learning SwiftUI and I am using version 3.0

  *TabView(selection: $selectedTab) {
      ... 
    }.onTapGesture {
        print(selectedTab) // This always give MainView 
    }*

I have also tried the above and it is always giving MainView

import SwiftUI
import Combine

struct TabViews: View {
    @State var selectedTab: Tab = .MainView
    @State private var firstPass = false
    
    var body: some View {
        
        TabView(selection: $selectedTab) {
            Text("Main View")
                .padding()
                .tabItem {
                    Image(systemName: "1.circle")
                    
                    Text("First")
                    
                }
                .tag(Tab.MainView)
            
            Text("Menu View")
            
                .padding()
                .tabItem {
                    Image(systemName: "2.circle")
                    
                    Text("Second")
                       
                }
                .tag(Tab.MenuView)
            
        }
        
        .onReceive(Just(selectedTab)) {
            print("Tapped!! \(selectedTab)")
            
 
            if $0 == .MainView  {
                
                if firstPass == true {
                    // update list
                    print("Update get more data")
                }
                firstPass = true
            }
            if $0 == .MenuView {
                print("2")
            }
        }
       
        
    }
}

extension TabViews {
    enum Tab: Hashable {
        case MainView
        case MenuView
        case RankingView
    }
}

struct TabView_Previews: PreviewProvider {
    static var previews: some View {
        TabViews()
    }
}

Solution

  • For your scenario the solution is to use proxy binding (to intercept every click) as was shown in second link from referenced question.

    Tested with Xcode 13 / iOS 15

    demo

    struct TabViews: View {
        @State var selectedTab: Tab = .MainView
        @State private var firstPass = false
    
        private var selection: Binding<Tab> { Binding(  // << this !!
            get: { selectedTab },
            set: {
                selectedTab = $0
    
                print("Tapped!! \(selectedTab)")
    
    
                if $0 == .MainView  {
    
                    if firstPass == true {
                        // update list
                        print("Update get more data")
    
                        firstPass = false  // << reset !!
                        return
                    }
                    firstPass = true
                }
                if $0 == .MenuView {
                    print("2")
                    firstPass = false
                }
            }
        )}
    
        var body: some View {
            TabView(selection: selection) {    // << here !!
                Text("Main View")
                    .padding()
                    .tabItem {
                        Image(systemName: "1.circle")
                        Text("First")
                    }
                    .tag(Tab.MainView)
    
                Text("Menu View")
                    .padding()
                    .tabItem {
                        Image(systemName: "2.circle")
                        Text("Second")
                    }
                    .tag(Tab.MenuView)
            }
        }
    }