2

I have 5 tabs each tab is a different view and load on appear . Once a tab is loaded snapper How can I make it reload again . I am new to SwiftUI and have not been able to get that done . So essentially I have a TabView View with 5 tabs and one of those tabs is called Home when home is clicked it calls another view called TimeLineView which gets data OnAppear from the database . Since it is OnAppear it works the first time but it does not get called again on subsequent taps . I would like to change that so that on every tap I can call OnAppear or call the function inside the OnAppear . Any suggestions would be great

struct TabView : View {
    @State var model: [MainModel]
    @State var selectedTab = "Home"
    var edges = UIApplication.shared.windows.first?.safeAreaInsets
    @Namespace var animation
    @StateObject var modelData = MainViewModel.ModelView()
    @State var IsMainView: MainViewEnum = MainViewEnum.MainView
    @Binding var mainModelValue: MainModelValue

    var body: some View {
        
        VStack(spacing: 0){
            
            GeometryReader{_ in
                
                ZStack{
                    
                    TimeLineView(model: model, isMainView: $IsMainView, newValue: mainModelValue, UserID: 0) // I would like to refresh this on every tap click
                        .opacity(selectedTab == "Home" ? 1 : 0)
                    
                    RankingView()
                        .opacity(selectedTab == "Ranking" ? 1 : 0)
                    
                    TypeCategoryView()
                        .opacity(selectedTab == "Post" ? 1 : 0)
                    
                    MenuView()
                        .opacity(selectedTab == "Menu" ? 1 : 0)
                    
                    InboxView()
                        .opacity(selectedTab == "Inbox" ? 1 : 0)
                    
                }
            }
            .onChange(of: selectedTab) { (_) in
                
                switch(selectedTab){
                
                case "Ranking": if !modelData.isRankingView{modelData.GetRankingView()}
                case "Post": if !modelData.isOrderLoad{modelData.loadOrders()}
                case "Menu": if !modelData.isRewardLoad{modelData.loadReward()}
                case "Inbox": if !modelData.InboxView{modelData.InboxLoad()}
                default: ()
                }
            }
            HStack(spacing: 0){
                
                ForEach(tabs,id: \.self){ tab in
                    
                    TabButton(title: tab, selectedTab: $selectedTab,animation: animation)
                    
                    if tab != tabs.last{
                        Spacer(minLength: 0)
                    }
                }
            }

        }
    }
}



struct TimeLineView: View {
    @State var model: [MainModel]
    @Binding var isMainView: MainViewEnum
    @State var shareSheet = false
    @State var PostIDState = 0
    @State var sharePost: String?
    @State var ProfileID: String?
    @State var FullNameClicked = false
    @State var FullName = ""
    @State var newValue = MainModelValue()
    @State var UserID: Int
    
    var body: some View {
        ZStack
        {
            Color(UIColor.white)
                .ignoresSafeArea()
            
            ScrollView(showsIndicators: false) {
                LazyVStack {
                  
                    if isMainView == MainViewEnum.MainView {
                    TestView(model: $model)
                    }
                    let result = model.sorted {
                        $0.id! > $1.id!
                    }
                    
                    ForEach(result) { value in
                       
                        Spacer()
                        VStack(alignment: .leading) {
                        HStack {
     
                           Text("\(value.initials!)")
                            .fontWeight(.bold)
                                .frame(width: 35, height: 35, alignment: .center)
                            .foregroundColor(Color(SystemColorPicked(picked: value.color)))
                                .padding()
                                .overlay(
                                    Circle()
                                    .stroke(Color.black, lineWidth: 1)
                                    .padding(6)
                                )
    
                            VStack(alignment: .leading, spacing: 1) {
                                HStack {
                                    Text("\(value.fullname)")
                                        .font(.system(size: 15))
                                        .bold()
                                        .onTapGesture {
                                            FullNameClicked.toggle()
                                            FullName = value.fullname
                                            ProfileID = String(value.profile_id)
                                        }
                                    Spacer()
                                   
                                }.padding(.leading, 13)
                        
                            }
                        }
                        
                            VStack(alignment: .leading, spacing: 1) {
                                HStack {
                                    
                                   if value.post.count >= 100 {

                              
                                    PostShowView(text: value.post)

                                   } else {
                                        Text("\(value.post)")
                                       .fixedSize(horizontal: false, vertical: true)
                                       .font(.system(size: 15))
                                    }
                   
                                }.padding(.leading, 90)

                                    Spacer()
                                    
                                }.padding(.leading, 90)
                                
                                VStack {
                                    Spacer()
                                    Divider()
                                }.padding(.leading, 90)
                                
                         }
          
                    }
                }.padding(25.0)
            }.padding(.top, 2.0)
            
        }
        .listRowInsets(.none)
        .onAppear(){
        // I would like this to execute every time this View is called
            MainViewModel().MainViewRequests(46, model: newValue) { data in
                self.model = data!
                
            }
            
        }
    }
}
user1591668
  • 2,591
  • 5
  • 41
  • 84

2 Answers2

1

Try with DeferView (taken from my answer in https://stackoverflow.com/a/61242931/12299030), like

DeferView  {
   TimeLineView(model: model, 
                isMainView: $IsMainView, 
                newValue: mainModelValue, 
                UserID: 0)
}.opacity(selectedTab == "Home" ? 1 : 0)
Asperi
  • 228,894
  • 20
  • 464
  • 690
1

In your case all your views will be created just once and onAppear() will be called just once at the same time for all of the views. If you want to call onAppear() every time, you need recreate views.

enum Tab {
    case Home, Ranking, Post, Menu, Inbox

}

    ...
  
    ZStack {
        switch selectedTab {
            case Home:
            TimeLineView(model: model, isMainView: $IsMainView, newValue:    mainModelValue, UserID: 0)

            case Ranking:
            RankingView()
            
            case Post:
            TypeCategoryView()

            case Menu:
            MenuView()

            case Inbox:
            InboxView()
        }
    }

   ... 

Also, I think, you can avoid using GeometryReader and Zstack and make your layout lighter.