4
  1. I created a custom tab bar
  2. I am using a switch statement to switch between my views
  3. The problem is that the view is being reloaded everytime I switch between tabs
  4. How do I "save" the state of the view when I switch between views?

So for example, if I am in the view of the first tab and I scroll down a bit on my scrollview, and I go to the 2nd tab, and then back to the first tab, it completely reloads the view and it doesn't show that I have scrolled down the page.

The Code:

struct Home: View {

   @State var selectedIndex = 0
   @State var presented = false

   let icons = ["house", "hands.sparkles", "plus", "message", "person"]



   var body: some View {
    
    VStack{
        
        Spacer().fullScreenCover(isPresented: $presented, content: {
            Text("Create Post Here")
            Button(action: {
                presented.toggle()
            }, label: {
                Text("Close")
            })
        })
        
        switch selectedIndex{
            
        case 0:
            HomePage()
        case 1:
            NavigationView(){
                Discover()
            }
        case 2:
            LogoutForNow()
        case 3:
            LogoutForNow()
        case 4:
            NavigationView(){
                Profile2()
            }
            
        default:
            HomePage()
        }
        
        
        
        
        HStack{
            ForEach(0..<5, id: \.self){number in
                
                Spacer()
                Button(action: {
                    
                    if number == 2{
                        presented.toggle()
                    }else{
                        self.selectedIndex = number
                    }
                    
                }, label: {
                    if number == 2{
                        Image(systemName: icons[number])
                            .font(.system(size: 25, weight: .regular, design: .default))
                            .foregroundColor(.white)
                            .frame(width: 50, height: 50)
                            .background(Color.blue)
                            .cornerRadius(25)
                    }else{
                        Image(systemName: icons[number])
                            .font(.system(size: 25, weight: .regular, design: .default))
                            .foregroundColor(selectedIndex == number ? .black : Color(UIColor.lightGray))
                    }
                })
                Spacer()
            }
        }
    }
    
}

}

1 Answers1

5

There are a few ways you could go about doing this.

Method 1: Changing Z-Index

Rather than showing either one view or another, you could keep both views being drawn at all times, but display the current, active view on top of the inactive views. You can do this by using the .zIndex() modifier.

Method 2: Using @SceneStorage (or @AppStorage)

The @SceneStorage and @AppStorage property wrappers both enable data persistence. For either one, you should keep track of the value you want to persist (such as the scroll height or something), and store it in SceneStorage/AppStorage.

@AppStorage is usually used for storing user preferences or constants, and would be the worse out of the two options, but is still possible. What you should, ideally, use is @SceneStorage. Essentially, @SceneStorage lets you store small amounts of data in the "scene", such as how far the user has scrolled. However, this data is destroyed when the scene is destroyed, such as when the user closes the app. You can find out more here

Also, if you're wondering how to store how far a user has scrolled in a ScrollView, you should use a ScrollViewReader :)

Stoic
  • 945
  • 12
  • 22
  • 1
    Using zIndex() with opacity() conditionally fixed my issue. For example .zIndex(selectedTab == .home ? 2 : 0).opacity(selectedTab == .home ? 1 : 0). Thank you @Stoic. – christostsang Nov 25 '22 at 11:57
  • No problem, just keep in mind that will slow your app down a bit since both views are being drawn. – Stoic Nov 25 '22 at 19:39
  • Actually, there are 4 views :), but I have a LaunchScreen that will "hide" this issue. – christostsang Nov 26 '22 at 15:57