I'm trying to build an authenticated flow in my app.
The app has a LoginScreenView that is going to appear first on the app. When logging in, we go to a TabView consisting of two Views, FirstView and SecondView. SecondView has a logout button, that returns the user to the login screen. On the FirstView we have a network call that is being performed always onAppear.
When the user logs out, we are on the SecondView, on the second tab; however both onAppear and onDisappear functions of the FirstView are being executed, even though FirstView is not on display.
This provokes in our use case to trigger the network call in the onAppear method of FirstView that will fail because we are not authenticated.
Here is my code.
This is LoginScreen:
struct LoginScreenView: View {
@EnvironmentObject private var authManager: AuthManager
var body: some View {
Button("Login") {
authManager.isLoggedIn = true
}
}
}
This is FirstView:
struct FirstView: View {
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Hello, world!")
}
.tabItem {
Label("Hello", systemImage: "globe")
}
.onAppear {
print("First ✅")
Task {
try await loadSomeStuffFromNetwork()
}
}
.onDisappear {
print("First ❌")
}
}
}
This is SecondView:
struct SecondView: View {
@EnvironmentObject private var authManager: AuthManager
var body: some View {
VStack {
Image(systemName: "flag.fill")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Goodbye, world!")
Button("Logout") {
authManager.isLoggedIn = false
}
}
.tabItem {
Label("Goodbye", systemImage: "flag")
}
.onAppear {
print("Second ✅")
}
.onDisappear {
print("Second ❌")
}
}
}
And this is the root view of the app:
struct ContentView: View {
@StateObject private var authManager = AuthManager()
var body: some View {
TabView {
Group {
if isLoggedIn {
FirstView()
SecondView()
} else {
LoginScreenView()
}
}
}
.environmentObject(authManager)
}
}
It's using the AuthManager declared in here:
final class AuthManager: ObservableObject {
@Published var isLoggedIn: Bool = false
}
As you can see in the code, we are trying to change the displayed views depending on whether we are logged in or not, and we use an if-else for that.
Do you think this code is OK? Do you feel that this might be a bug? I feel like this should work out of the spot, but I don't know if I'm missing anything.
I saw this question from 2022, but it seems it never got resolved (apart from the workaround of adding a condition of being logged in to perform the network call).
Also, saw this other one where they propose to use a @State variable to make the view only perform one network call instead of everytime it appears (or SwiftUI decides it to appear).
Are we OK on this train of thought? Should we try to build our network call in some other way?
I would prefer to avoid having to add a check to see if we are authenticated every time we perform the call, because that might lead us to unexpected edge cases on our flows.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hello there!
In our team we are looking for a way to connect to an external device to get and send live information through it.
We need to do this because our app is required to work on offline environments and we can't expect to have Internet connection.
The device that we connect against is a PC that may not have Internet connection as well.
Because of that, we decided to implement live updates via WiFi:
The PC generates a WiFi access point.
The PC launches an internal server in a local IP of that local network.
The phone connects to the access point and queries the PC through the server's local IP.
Also we wanted to have security for this interaction. So we agreed on doing MTLS on the connection step, so we can both verify that the server is talking to the phone and viceversa.
We do this storing p12 on both phone and PC and verifying their identities via certificates that contain those ids.
In our phone configuration, we use the NEHotspotConfigurationManager to connect to the PC's network. Then we make sure that we are connected to the WiFi network using NEHotspotNetwork.fetchCurrent.
After that, we are using URLSession to connect to the PC's server with the local IP. We are using the SessionDelegate and implement the didReceiveChallenge method. We do it in a very similar way to the one found in this other DevForum thread.
Do you think we are following the right approach to this problem?
Do you see any potential gaps in this implementation?