问题
I have a class which has 2 sets of getter & setters. 1 set is the traditional type. These work as expected:
var userEmail : String
{
get {
return UserDefaults.standard.string(forKey: UserDefaultKeys.profileEmail) ?? ""
}
set (newValue) {
UserDefaults.standard.set(newValue, forKey: UserDefaultKeys.profileEmail)
UserDefaults.standard.synchronize()
}
}
var podSerialNum : Int
{
get {
return UserDefaults.standard.integer(forKey: UserDefaultKeys.profilePodSN)
}
set (newValue) {
UserDefaults.standard.set(newValue, forKey: UserDefaultKeys.profilePodSN)
UserDefaults.standard.synchronize()
}
}
var podID : Int
{
get {
return UserDefaults.standard.integer(forKey: UserDefaultKeys.profilePodID)
}
set (newValue) {
UserDefaults.standard.set(newValue, forKey: UserDefaultKeys.profilePodID)
UserDefaults.standard.synchronize()
}
}
The other gets/sets all properties at once.
var userProfile: (email:String?, podSn:String?, podId:String?)
{
get {
return ( UserDefaults.standard.value(forKey: UserDefaultKeys.profileEmail) as? String,
UserDefaults.standard.value(forKey: UserDefaultKeys.profilePodSN) as? String,
UserDefaults.standard.value(forKey: UserDefaultKeys.profilePodID) as? String)
}
set {
UserDefaults.standard.set(newValue.email, forKey: UserDefaultKeys.profileEmail)
UserDefaults.standard.set(newValue.podSn, forKey: UserDefaultKeys.profilePodSN)
UserDefaults.standard.set(newValue.podId, forKey: UserDefaultKeys.profilePodID)
UserDefaults.standard.synchronize()
}
}
userProfile.podSn
always returns nil. However userProfile.email
& userProfile.podId
work as expected. Also, the direct getter (podSerialNum
) works.
What am I missing?
回答1:
Adding a few steps to understand:
UserDefaults.standard.value(forKey: UserDefaultKeys.profilePodSN) as? String
=>
let podSNFromUserDefaults = UserDefaults.standard.value(forKey: UserDefaultKeys.profilePodSN)
let podSNAsString = podSNFromUserDefaults as? String
Well, you'll see that podSNFromUserDefaults
is not nil
, it's podSNAsString
which is.
Why ? Because podSNFromUserDefaults
is an Int
/NSNumber
, not a String
. You can't cast it as a String
like that. Use String(myInt)
.
And since we already know it's an Int, like you did for each single call, use integer(forKey:)
, and directly string(forKey:)
also for the profileEmail
, you don't need the as? String
afterwards.
var userProfile: (email: String?, podSn: String?, podId: String?)
{
get {
return (UserDefaults.standard.string(forKey: UserDefaultKeys.profileEmail),
String(UserDefaults.standard.integer(forKey: UserDefaultKeys.profilePodSN)),
String(UserDefaults.standard.integer(forKey: UserDefaultKeys.profilePodID))
}
}
Side note:
You should get rid of the UserDefaults.standard.synchronize()
.
Tip:
If you have issues, don't forget to break multiple calls made in one line into various ones. It should be then easier to debug which step exactly doesn't work.
来源:https://stackoverflow.com/questions/55300399/why-does-1-of-these-getter-setters-work-and-the-others-dont