Bassman
Bassman

Reputation: 413

Why does 1 of these getter/setters work and the others don't

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?

Upvotes: 0

Views: 99

Answers (1)

Larme
Larme

Reputation: 26026

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.

Upvotes: 1

Related Questions