At the beginning I'm declaring:
@AppStorage("userid") var userid: Int = 0
then couple lines of code down below:
if(userid == 0){
NavigationLink(destination: Login(), label: {
Image(systemName: "person.circle.fill")
.resizable()
.aspectRatio(contentMode: .fit).frame(width: 32)
.foregroundColor(Color(UIColor(named: "IconColor")!))
})
}else{
NavigationLink(destination: Profile(), label: {
AsyncImage(url: URL(string: "https://cdn.icon-icons.com/icons2/2108/PNG/512/stackoverflow_icon_130823.png")) { phase in
switch phase {
case .empty:
Image(systemName: "person.circle.fill")
.resizable()
.aspectRatio(contentMode: .fit).frame(width: 32)
.foregroundColor(Color(UIColor(named: "IconColor")!))
case .success(let image):
image.resizable()
.aspectRatio(contentMode: .fit)
.frame(maxWidth: 32)
case .failure:
Image(systemName: "person.circle.fill")
.resizable()
.aspectRatio(contentMode: .fit).frame(width: 32)
.foregroundColor(Color(UIColor(named: "IconColor")!))
@unknown default:
Image(systemName: "person.circle.fill")
.resizable()
.aspectRatio(contentMode: .fit).frame(width: 32)
.foregroundColor(Color(UIColor(named: "IconColor")!))
}
}
})
}
Problem 1:
When the userid is 0 and I tap the image to get to Login():
struct Login: View {
@AppStorage("userid") var userid: Int = 0
var body: some View{
Button(action: {
userid = 777
}) {
Text("login")
}
}
}
to change the AppStorage userid to 777 by clicking on login then Login() view closes which I don't want, the condition in the main view correctly changed to destination: Profile() and shows the downloaded image though.
Problem 2:
When I tap the image to go to Profile():
struct Profile: View {
@AppStorage("userid") var userid: Int = 0
var body: some View{
Button(action: {
userid = 0
}) {
Text("profile: logout")
}
}
}
to click on logout then the view doesn't close but apparently AppStorage userid doesn't get changed to 0 because the main view still shows the downloaded image and the destination is still Profile().
How to do this correctly?
CodePudding user response:
What I think you need to take a look at is the isActive
argument for a NavigationLink
that allows you to programmatically show a View. Here are the docs.
What you can do is create a property like hasLoggedIn
and pass it to the LoginView
and to the NavigationLink
for the ProfileView
. Check out the code snippet I just wrote, I guess it does what you want.
struct MainView: View {
@AppStorage("userid") var userId: Int = 0
@State var hasLoggedIn = false
var body: some View {
NavigationView {
List {
if (userId == 0) {
NavigationLink {
LoginView(hasLoggedIn: $hasLoggedIn)
} label: {
Text("Login")
}
} else {
NavigationLink(isActive: $hasLoggedIn) {
ProfileView()
} label: {
Text("Profile")
}
}
}
}
}
}
struct LoginView: View {
@AppStorage("userid") var userId: Int = 0
@Binding var hasLoggedIn: Bool
var body: some View {
Button {
userId = 777
hasLoggedIn = true
} label: {
Text("Login")
}
}
}
struct ProfileView: View {
@AppStorage("userid") var userId: Int = 0
var body: some View {
Button {
userId = 0
} label: {
Text("Profile")
}
}
}
Regarding Problem 2, I didn't face it. Everything worked for you were describing, maybe I misunderstood you.
Oh and definitely take a look at the MVVM pattern as it may be not the best solution to put everything in the Views