I have an application which uses a rest api for authentication. The problem I am facing now is that I save user's token in my UserDefaults and username too because those are the two main parameters needed to get user details. so if the application is closed by the user he should still be able to view the view his profile when he opens the application back but instead the profile returns empty details. this is the UserDefaults codes that I have
let defaults = UserDefaults.standard
var isLoggedIn : Bool {
get {
return defaults.bool(forKey: LOGGED_IN_KEY)
}
set {
defaults.set(newValue, forKey: LOGGED_IN_KEY)
}
}
//Auth Token
var authToken: String {
get {
return defaults.value(forKey: TOKEN_KEY) as? String ?? ""
}
set {
defaults.set(newValue, forKey: TOKEN_KEY)
}
}
var userUsername: String {
get {
return defaults.value(forKey: USERNAME_KEY) as? String ?? ""
}
set {
defaults.set(newValue, forKey: USERNAME_KEY)
}
}
I have no idea why it isnt retrieving the user data.
My second question is when I logout the user, all the users details are cleared as expected but the moment I try loging in with a different user, the new user's authToken and details gets printed in the console but the user profile returns the profile of the previous person. which is not supposed to be. my code is shown below
func logoutUser() -> Void {
pk = 0
username = ""
email = ""
firstName = ""
lastName = ""
AuthService.instance.isLoggedIn = false
AuthService.instance.authToken = ""
AuthService.instance.userUsername = ""
}
@IBAction func logoutPressed(_ sender: Any) {
UserDataService.instance.logoutUser()
dismiss(animated: true, completion: nil)
}
I would also like to add that when i run the api using postman i get a response that "detail": "Signature has expired."
so i had to input the new token in the header so it displays the user details again
enum SettingKeys: String {
case authToken
//...
}
struct Settings {
static var authToken: String? {
get { return UserDefaults.standard.string(forKey: SettingKeys.authToken.rawValue) }
set(value) { UserDefaults.standard.set(value, forKey: SettingKeys.authToken.rawValue) }
}
static func deleteAll(exclude: [SettingKeys] = []) {
let saveKeys = exclude.map({ $0.rawValue })
for key in UserDefaults.standard.dictionaryRepresentation().keys {
if !saveKeys.contains(key) {
UserDefaults.standard.removeObject(forKey: key)
}
}
}
}
I recommend storing keys as Enum, because then u can use it like that:
//Read
if let token = Settings.authToken {
//do something
}
//Write
Settings.authToken = "123456"
//Delete settings
Settings.deleteAll()
//or choose what to leave
Settings.deleteAll(exclude: [.authToken])
And it's worth to mention that defaults.synchronize()
is deprecated.