Removing a key from NSUserDefaults not working - ios

I have a logout function in my app. Seems to be a weird problem where it doesn't save the NSUserDefaults. Here I simply want to remove the key. However after logging out if I then open the app again it will find that this key is still in the NSUserDefaults.
func didLogout() {
// Clear user data
let settings = NSUserDefaults.standardUserDefaults()
settings.removeObjectForKey("userData")
settings.synchronize()
unregisterForRemoteNotifications()
openLoginScreen()
}
Any ideas what I could be doing wrong here?

try this
DispatchQueue.main.async {
UserDefaults.standard.removeObject(forKey: YOUR_KEY_HERE)
}
helped for me

removeObjectForKey(_:)
Removing a default has no effect on the value returned by the
objectForKey: method if the same key exists in a domain that precedes
the standard application domain in the search list.
Just use another key instead of userData. It might exists in another domain.

The code above is correct. The key will be still there, but it will return only nil value. So, when user logout you can set
NSUserDefaults.standardUserDefaults().removeObjectForKey("userData")
and when new user login you can set new value by checking
if NSUserDefaults.standardUserDefaults().objectForKey("userData") == nil

One of our (XCTest) unit tests was failing every other run. It turned out that -removeObjectForKey: was — inexplicably — only working every other run. I verified this with defaults.dictionaryRepresentation before and after -removeObjectForKey:. I thought perhaps the keys were being added to two domains and the first remove wasn't getting them both (the docs say this can happen) so I cleverly added a second remove, but that also had no effect. My solution was to set the key to the uninitialized value instead.
Any ideas?

There is no issue in your above code you might have set data in app delegate or when you login your app, or you have mistyped key value.
If you want to clear all data. This will Work
let appDomain = NSBundle.mainBundle().bundleIdentifier!
NSUserDefaults.standardUserDefaults().removePersistentDomainForName(appDomain)

I did the following to delete the userdefault of the app on user loggout
private static let userDefaults = NSUserDefaults.standardUserDefaults()
private static let userTokenKey = "userTokenKey"
userDefaults.removeObjectForKey(userTokenKey)
userDefaults.synchronize()

Related

set value in UserDefaults synchronously

I am trying to save boolean in UserDefault in swift.
so when I set value in userDefault, my very next instruction is to switch to view controller and close the current view controller.
so, what is happening now is, sometimes userDefault saves the value in DB, and sometimes it doesn't.
I read documentation from Apple
https://developer.apple.com/documentation/foundation/userdefaults
and found that
At runtime, you use UserDefaults objects to read the defaults that your app uses from a user’s defaults database. UserDefaults caches the information to avoid having to open the user’s defaults database each time you need a default value. When you set a default value, it’s changed synchronously within your process, and asynchronously to persistent storage and other processes.
so, I guess because in the very next line I open a new controller and close the current one so due to which there is inconsistency.
here is my code
func setWalkthroughShown(completionHandler: #escaping ()->()) {
UserDefaults.standard.set(true, forKey: isWalkthroughCompleted)
UserDefaults.standard.synchronize()
completionHandler()
}
I even called UserDefaults.standard.synchronize() so that operation may become synchronous.
even though in the documentation it is clearly written not to use this function.
can someone please guide me where I am wrong? how can I save across all places before closing the current process?
this is the function by which I am retrieving value
func isWalkthroughShown() -> Bool {
return UserDefaults.standard.bool(forKey: isWalkthroughCompleted)
}
here isWalkthroughCompleted is a string and you can see I am using same string for saving and retrieving value
Actually, there was no syntax error in coding.
I was actually testing it in the wrong way.
after submitting for the request of saving data in userdefaults, I was recompiling immediately and as value stores asynchronously so sometimes due to killing of the process I was getting this issue.
thanks to #matt.
for detail iOS UserDefaults falls behind saved content

Is it fine to access NSUserDefaults/UserDefaults frequently?

I have a login view controller in which the user enters their preferences like whether or not he wants to activate certain UI features.
I store these as variables whose getters and setters directly access UserDefaults, here is an example of one of these:
class Preferences {
static var likesSpaghetti : Bool {
set (likesSpaghetti) {
UserDefaults.standard.set(likesSpaghetti, forKey: "likesSpaghetti")
}
get {
return UserDefaults.standard.bool(forKey: "likesSpaghetti")
}
}
}
So that whenever I want to set any of these I simply write something like this:
Preferences.likesSpaghetti = false
Now, my question is: Can I set these variables every time the user flicks the on/off switch or should I keep the preference represented as a local variable and then only set:
Preferences.likesSpaghetti = spaghettiSwitch.isOn
when the user segue's away from the loginViewController? Is every access of UserDefault instant and quick? or is it laggy and should be used mercifully?
Edit after closing this question: So I learned to not prematurely optimize, and that it is probably ok within the scope of a few dozen elements. So I should be fine. I'm going to just update every time the user modifies anything so that my code is a lot easier to read and maintain.
Thanks everyone!
Your code is just fine. Don't worry about such optimizations until you actually encounter an issue. Trust that UserDefaults is implemented smartly (because it is). There is nothing "laggy" about setting something as simple as a Bool in UserDefaults.
You also wish to review another one of my answers which is related to this question: When and why should you use NSUserDefaults's synchronize() method?
Actually userDefaults (it's originally a plist file) is used for this purpose which is storing app settings and that light-wight content creating a variable may consum memory if you have to configure many of them , besides not reflecting the new setting change directly to defaults made by user , may cause un-expectable old settings to happen at the time of change such as a localized alert or part of code (such as push notification callback) that check the same setting where the user thinks it's already reflected
Adding to both #rmaddy #Sh_Khan, if you think about the security aspect of it, NSUserDafault is exactly for the details which is app specific such as settings, preferences or some configurations which are not security sensitive while things like passwords, usernames and sensitive data are not recommended to store in UserDefaults. You should use services like keychain which is encrypted for such data.

UserDefault return different values

I have a very weird problem in Swift3. I want to keep an user logged into application after he has already authenticated in his last session.
My problem is that UserDefaults return sometimes true, sometimes false even if is logged in his account. The problem makes me crazy. I use an bool value stored in UserDefaults, I tried to save a specific string but the problem persist.
Anyone had this problem? Any solutions?
Here is the code when I log in:
UserDefaults.standard.set(true, forKey: LOGIN)
And this is my code in AppDelegate in didFinishLaunchingWithOptions method:
if UserDefaults.standard.bool(forKey: LOGIN) {
AppData().updateUserInformation()
}
I suggest calling UserDefaults.standard.synchronize() after setting UserDefaults values. A lot of developers say that you don't need to do this and that iOS will take care of it for you.
But I've found that not always to be the case, especially when reading values shortly after setting them, or if the app exits before they are synchronized and therefore are lost.

NSUSerDefault not updating my global variable for swift

I have a signin/out function for my app. However, I relised that when I logout, something is weird with my global user variable
I have a global variable under my constants.swift
var CURRENT_USER_UID = NSUserDefaults.standardUserDefaults().valueForKey("currentUserUid") as? String
However, when I logout from the current user and log a new one in, at the end of the sign in function, I have the following print statement
print("Sign in successfully. user.uid = \(user?.uid)")
print("CURRENT_USER_UID = \(CURRENT_USER_UID))")
print("NSUserDefaults.standardUserDefaults().valueForKey(KEY_USER_UID) \(NSUserDefaults.standardUserDefaults().valueForKey(KEY_USER_UID))")
These prints out
Sign in successfully. user.uid = Optional("3P9uavuLtDQZV8ColwTseBIrY4w1")
CURRENT_USER_UID = Optional("hakV4smGyveurPhFN7g9rad4xsP2"))
NSUserDefaults.standardUserDefaults().valueForKey("currentUserUid") Optional(3P9uavuLtDQZV8ColwTseBIrY4w1)
"hakV4smGyveurPhFN7g9rad4xsP2" was the previous user's userUID.
"3P9uavuLtDQZV8ColwTseBIrY4w1" is the current user's UID which I only just logged in. If working correctly, I would expect all three to be "3P9uavuLtDQZV8ColwTseBIrY4w1"
Does anyone know why my CURRENT_USER_UID does not return the same thing as NSUserDefaults.standardUserDefaults().valueForKey("currentUserUid") ??
The CURRENT_USER_ID won't reflect the changes happened to the NSUserDefaults. The initially assigned value won't change, the value won't be calculated again.
For fixing the issue, Either you should assign the changed user id to CURRENT_USER_ID (When that changes), or you can write a global function which returns the user id (I prefer this approach over changing the global variable in your code):
func getCurrentUserId() -> String?
{
return NSUserDefaults.standardUserDefaults().valueForKey("currentUserUid") as? String
}
Your global variable is initialised when the app is launched, so it is given the value that NSUserDefaults.standardUserDefaults().valueForKey("currentUserUid") returns at that point. When user defaults is updated the global isn't magically re-initialised. You need to update it yourself.
The simple (but wrong) solution is to assign the uid value to CURRENT_USER_ID when you complete the login and save it to NSUserDefaults.
The right solution is not to use global variables. You should encapsulate your user state in an appropriate class and use this to login/logout/obtain the current user.

Save variable in swift even when app is turned off

Do you guys know how to save a var in swift, even when the app is closed.
When someone opens the app on his phone for the first time he can choose a name, what I want is, if he selected a name at the first time. He don't need to choose anymore and the name is saved even when the app is closed and turned on again.
Thanks!
Best way is to use NSUserDefaults.
With the NSUserDefaults class, you can save settings and properties related to application or user data.
ex:
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject("Foo", forKey: "name")
and then to read
if let name = defaults.stringForKey("name")
{
println(name)
}

Resources