What is the difference between object(forKey:) and value(forKey:) in UserDefaults?
value(forKey:)
is from key-value coding, and not a direct method of UserDefaults
.
Never use value(forKey:)
on UserDefaults
or Dictionary
or any other class unless you have a clearly understood need to use key-value coding to get the desired result.
When you don't have such a need, use the standard access methods provided by the class in question (such as UserDefaults object(forKey:)
.
UserDefaults between Objective-C and Swift
[NS]UserDefaults
is backed by a plist and a dictionary. The Objective-C string was saved to the plist as a <string>Some Text</string>
.
That same plist loaded in Swift gives a string for that key.
So you should have no issue using UserDefaults.string
to read the value stored with Objective-C. Of course you still need to verify the value actually exists.
if let str = UserDefaults.standard.string(forKey: "textKey") {
print("Found \(str)")
} else {
print("No string for key")
}
Even if the original value isn't a string, using UserDefault.string
is safe. It will simply return nil
for non-string values.
With regard to NSDictionary
and NSMutableDictionary
, note that UserDefaults
only retrieves immutable NSDictionary
. You can't read an NSMutableDictionary
(or array) from UserDefaults
.
Note you can safely use a Swift dictionary to read the original NSDictionary
. No need to use Objective-C classes.
Difference remove object and becoming nil for UserDefaults - Swift
No difference at all.
If you wanna remove object, use second variant for better readability
First one useful when you have an optional value and don't want care if it's nil, like
var a: String? = "hello"
UserDefaults.standard.set(a, forKey: "token")
b = nil
UserDefaults.standard.set(a, forKey: "token")
Otherwise you would have to check value and choose to either insert or delete
How can I use UserDefaults in Swift?
ref: NSUserdefault objectTypes
Swift 3 and above
Store
UserDefaults.standard.set(true, forKey: "Key") //Bool
UserDefaults.standard.set(1, forKey: "Key") //Integer
UserDefaults.standard.set("TEST", forKey: "Key") //setObject
Retrieve
UserDefaults.standard.bool(forKey: "Key")
UserDefaults.standard.integer(forKey: "Key")
UserDefaults.standard.string(forKey: "Key")
Remove
UserDefaults.standard.removeObject(forKey: "Key")
Remove all Keys
if let appDomain = Bundle.main.bundleIdentifier {
UserDefaults.standard.removePersistentDomain(forName: appDomain)
}
Swift 2 and below
Store
NSUserDefaults.standardUserDefaults().setObject(newValue, forKey: "yourkey")
NSUserDefaults.standardUserDefaults().synchronize()
Retrieve
var returnValue: [NSString]? = NSUserDefaults.standardUserDefaults().objectForKey("yourkey") as? [NSString]
Remove
NSUserDefaults.standardUserDefaults().removeObjectForKey("yourkey")
Register
registerDefaults: adds the registrationDictionary to the last item in every search list. This means that after NSUserDefaults has looked for a value in every other valid location, it will look in registered defaults, making them useful as a "fallback" value. Registered defaults are never stored between runs of an application, and are visible only to the application that registers them.
Default values from Defaults Configuration Files will automatically be registered.
for example detect the app from launch , create the struct for save launch
struct DetectLaunch {
static let keyforLaunch = "validateFirstlunch"
static var isFirst: Bool {
get {
return UserDefaults.standard.bool(forKey: keyforLaunch)
}
set {
UserDefaults.standard.set(newValue, forKey: keyforLaunch)
}
}
}
Register default values on app launch:
UserDefaults.standard.register(defaults: [
DetectLaunch.isFirst: true
])
remove the value on app termination:
func applicationWillTerminate(_ application: UIApplication) {
DetectLaunch.isFirst = false
}
and check the condition as
if DetectLaunch.isFirst {
// app launched from first
}
UserDefaults suite name
another one property suite name, mostly its used for App Groups concept, the example scenario I taken from here :
The use case is that I want to separate my UserDefaults (different business logic may require Userdefaults to be grouped separately) by an identifier just like Android's SharedPreferences. For example, when a user in my app clicks on logout button, I would want to clear his account related defaults but not location of the the device.
let user = UserDefaults(suiteName:"User")
use of userDefaults synchronize, the detail info has added in the duplicate answer.
How to change the type of a value from UserDefaults?
First of all, you can use UserDefaults.standar.integer(forKey:)
to retrieve a value of type Int
. Secondly, you should store the casted value once and shouldn't retrieve it several times (currently you retrieve it 3 times instead of just 1).
Moreover, your logic is flawed. You are trying to compare the value if the retrieved value was nil
. So you are not just trying to compare Any?
to Int
, you are trying to compare nil
to Int
.
func setScore() {
let defaults = UserDefaults.standard
let newScore = score
if let highScore = defaults.object(forKey: "HighScore") as? Int {
print(highScore)
if highScore < Int(newScore) {
defaults.set(newScore, forKey: "HighScore")
}
}
}
The same function, but retrieving the Int
value straight away without having to cast (UserDefaults.integer(forKey:)
returns 0 if there is no value stored for that key).
func setScore() {
let newScore = score
if UserDefaults.standard.integer(forKey: "HighScore") < Int(newScore) {
defaults.set(newScore, forKey: "HighScore")
}
}
}
NSUserDefaults - How to tell if a key exists
objectForKey:
will return nil
if it doesn't exist.
checking for an optional UserDefaults.standard.value
You are completely misusing optionals, forced-unwrapping, and if let
.
You should also avoid using value(forKey:)
. And avoid needless type declarations. Let Swift infer the type when appropriate.
Your if
should be:
if let facebookDetails = UserDefaults.standard.dictionary(forKey: "facebookDetails") {
}
You should also avoid the force-unwrapping unless you know for sure that the value (or cast) will always succeed.
And be consistent in your code. On one line you do:
let picture:Dictionary = (facebookDetails["picture"] as? [String:Any])!
and another you do:
let fb_pic_data_url:String = fb_pic_data["url"] as! String
Why take two different approaches to forcing the case and the optional?
Related Topics
Ambiguous Use of 'Filter' When Converting Project to Swift 4
Errors Encountered While Discovering Extensions: Error Domain=Pluginkit Code=13 "Query Cancelled"
Custom Vibration in iOS 8 - Swift
Override UIgesturerecognizer Touchesbegan
How to Present a UIcollectionview in Swiftui with UIviewcontrollerrepresentable
How to Set First Responder for Nstextview in Swift
Why Do I Get Source Kit Service Terminated Error
Finding The First Non-Repeating Character in a String Using Swift
How to Condense Unwrapping Multiple Optionals in Swift
Swift - Boundingbox Cause Exc_Bad_Access (Code=1)
Check Os Version Using Swift on MAC Os X
Cannot Assign to Value: 'self' Is Immutable
How to Cast Sockaddr_In to Sockaddr in Swift
How to Put View on Top of All Other Views in Swiftui
Avspeechrecognizer: Required Condition Is False: _Recordingtap == Nil Error in Swift3