Help me understand .onAppear/.task aka app authentication state

I am trying to make simple app auth. In ContentView I have two tabs, each tab will have their own .task{} in which I will make an HTTP request to obtain some data.

The problem that I am facing is when you open the app, switch tabs and tap "toggle" at the top, you will see in the console that both .task{} and .onAppear{} has been called event tho these views wren't visible at all. Why? And how to make API calls only when app states is logged

As a workaround I could add extra check in each .task to check the app state but it doesn't seems right...

import SwiftUI

@main
struct myApp: App {
  
  @StateObject private var auth: Auth = Auth()
  
    var body: some Scene {
        WindowGroup {
          if auth.isLogged {
            ContentView()
              .environmentObject(auth)
          } else {
            VStack {
              Button("toggle auth") {
                auth.isLogged.toggle()
              }
            }
          }
        }
    }
}


@MainActor
class Auth: ObservableObject {
  @Published var isLogged: Bool = false
}


struct ContentView: View {
  
  // Annimatin Properties
  @State private var expanded: Bool = false
  @Namespace private var animation
  
  @EnvironmentObject var auth: Auth
  
  
  var body: some View {
    
    Button("toggle") {
      self.auth.isLogged.toggle()
    }
    
    TabView {
      SampleTab("Listen Now", "play.circle.fill")
      SampleTab("Browse", "square.grid.2x2.fill")
    }
    
  }
  
  @ViewBuilder
  func CustomBottomSheet() -> some View {
    // Animating sheet backgrund (To look like it's expanding from the Bottom)
    VStack {
      Text("Hello")
    }
    .frame(height: 70)
    .overlay(alignment: .bottom, content: {
      Rectangle()
        .fill(.gray.opacity(0.3))
        .frame(height: 1)
    })
    .offset(y: -49)
  }
  
  @ViewBuilder
  func SampleTab(_ title: String, _ icon: String) -> some View {
    // iOS Bug, it can be avoided by wrapping the view inside ScrollView
    
    ScrollView(.vertical, showsIndicators: false, content: {
      Text(title)
        .padding(.top, 25)
    })
      .tabItem {
        Image(systemName: icon)
        Text(title)
      }
      .onAppear {
        print("======= onappear \(title)")
      }
      .task {
       // I am gonna make an HTPP request here...
        print("======= task \(title)")
      }
  }
}

Replies

You can use onChange(appState.isLogged) to reach your purpose, and about the other question, I would try to set the on appear modifier upper, maybe just after the scroll view, and if it doesn't work after the text padding.

Let me know what happens.

Add a Comment