I would like to initialize a variable obj
by taking it from UserDefaults
, which returns a String?
, and if it's nil
build the value and assign it.
The following code works, but, at the end, my obj
is a String?
while I want it to be a String
(since it can't be nil
at this stage).
var obj = UserDefaults.standard.string(forKey: "my_key")// Here, obj is a String?
if obj == nil {
obj = ProcessInfo.processInfo.globallyUniqueString// Returns, a String
defaults.set(obj, forKey: "my_key")
defaults.synchronize()
}
// Here, obj is still a String?
Is there a good pattern / best practice for this kind of situation ?
You can use the nil-coalescing operator ??
with an "immediately evaluated closure":
let obj = UserDefaults.standard.string(forKey: "my_key") ?? {
let obj = ProcessInfo.processInfo.globallyUniqueString
UserDefaults.standard.set(obj, forKey: "my_key")
return obj
}()
print(obj) // Type is `String`
If the user default is not set, the closure is executed. The closure creates and sets the user default (using a local obj
variable) and returns it to the caller, so that it is assigned to the outer obj
variable.
Optional Binding. You can read up on it here
let obj: String
if let string = UserDefaults.standard.string(forKey: "my_key") {
obj = string
} else {
obj = ProcessInfo.processInfo.globallyUniqueString
UserDefaults.standard.set(obj, forKey: "my_key")
}
print(obj)
Use either guard let
or if let
.
1) guard let
(not common for your case, though)
guard let obj = UserDefaults.standard.string(forKey: "my_key") else {
// guard failed - obj is nil; perform something and return
obj = ProcessInfo.processInfo.globallyUniqueString
defaults.set(obj, forKey: "my_key")
return
}
// obj is not nil, you have it at your disposal
print(obj)
2) if let
if let obj = UserDefaults.standard.string(forKey: "my_key") {
// obj exists
} else {
let obj = ProcessInfo.processInfo.globallyUniqueString
defaults.set(obj, forKey: "my_key")
print(obj)
}
(!) Also, there really is no more need to call defaults.synchronize()
:
Waits for any pending asynchronous updates to the defaults database and returns; this method is unnecessary and shouldn't be used.
https://developer.apple.com/documentation/foundation/nsuserdefaults/1414005-synchronize
You can also use an implicitly unwrapped optional, like this:
var obj: String! = UserDefaults.standard.string(forKey: "my_key")// Here, obj is a (possibly `nil`) `String!`
if obj == nil {
obj = ProcessInfo.processInfo.globallyUniqueString // Returns, a String
defaults.set(obj, forKey: "my_key")
defaults.synchronize()
}
// Here, obj is a non-`nil` `String!`, which will work the same as a `String`
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.