0

In my app, I have a View which is set to either a login View or a home TabView, depending on if the user is logged in. From the TabView, the user can go to a profile popover and logout. I want to switch back to the login View from this popover.

I tried dismissing the popover and immediately logging the user out, but when I test on a real device, what happens is the popover stays on the screen and also no longer responds to user input. It can't be dismissed. I'm not sure why, and what should I do instead?

Starting View:

struct StartView: View {
    @EnvironmentObject var authService:AuthService
    
    var body: some View {
        ZStack {
            if(!authService.signedIn) {
                LoginView()
            } else {
                HomeView()
            }
        }
    }
}

Home TabView:

import SwiftUI

struct HomeView: View {
    @State private var showingProfilePopover:Bool = false
    
    var body: some View {
        TabView {
            NavigationView {
                VStack(alignment: .leading) {
                    Text("Tab 1")
                    .padding(.leading, 30)
                }
                .toolbar {
                    ToolbarItem {
                        Button(action: {
                            showingProfilePopover = true
                            }, label: {
                                Image(systemName: "person.crop.circle").imageScale(.large)
                            }
                        )
                    }
                }
                
            }.popover(isPresented: $showingProfilePopover) {
                ProfileView(isPresented: $showingProfilePopover)
            }
            .tabItem {
                Image(systemName: "list.bullet")
                    .font(.system(size: 26))
                Text("Tab 1")
            }
            
            
            
            NavigationView {
                VStack(alignment: .leading) {
                    Text("Tab 2")
                }
            }.tabItem {
                Image(systemName: "books.vertical")
                    .font(.system(size: 26))
                Text("Tab 2")
            }
        }
        
    }
}

Popover:

struct ProfileView: View {
    @EnvironmentObject var authService:AuthService
    @Binding var isPresented: Bool
    
    var body: some View {
        Button("Logout") {
            // Close the popup and switch to LoginView
            print("Tapped logout")
            isPresented = false
            
            authService.signOut()
        }
        .font(Font.custom("OpenSans-Regular", size: 18))
            .padding(20)
    }
}

LoginView:

import SwiftUI

struct LoginView: View {
    @EnvironmentObject var authService:AuthService
    
    var body: some View {
        VStack {
            Button("Login") {
                self.authService.signIn()
            }.buttonStyle(.borderedProminent)
        }
    }
}

AuthService:

import SwiftUI

class AuthService: ObservableObject {
    @Published var signedIn:Bool
    
    init(signedIn:Bool) {
        self.signedIn = signedIn
    }
    
    func signIn() {
        self.signedIn = true
    }
    
    func signOut(){
        self.signedIn = false
    }
}

2 Answers2

1

Seems like an issue connected to .popover. I can reproduce the issue, but it works just fine using .sheet instead.

Consider attaching the .popover on the TabView or the Button itself then it seems to work just fine.

hallo
  • 825
  • 1
  • 7
  • 10
0

I realized the issue only happens on the older versions of iOS. it works fine on iOS 15, but not on iOS 14 and below iOS 14.

@main
struct LoginApp: App {
    let authService: AuthService
    
    init() {
        authService = AuthService(signedIn: false)
    }
    
    var body: some Scene {
        WindowGroup {
            StartView().environmentObject(authService)
        }
    }
}

This is iPhone 8, iOS 14

enter image description here

Tran To
  • 285
  • 1
  • 6