nmdias / DefaultsKit

Simple, Strongly Typed UserDefaults for iOS, macOS and tvOS
MIT License
1.43k stars 95 forks source link

How to extend Key class Key with keys? #9

Closed toseefkhilji closed 6 years ago

toseefkhilji commented 6 years ago

Hello,

Awesome Library!!!

I am trying for the below things:

My Goal defaults.set(true, forKey: .isUserLoggedIn)

Currently I'm doing in this way:

enum Keys {
    static let isUserLoggedIn = Key<Bool>("isUserLoggedIn")
}

defaults.set(true, forKey: Keys.isUserLoggedIn)

Please guide me.

nmdias commented 6 years ago

Hello @toseefkhilji,

The way you're doing it, it is not possible.

When you are getting/setting a key, you need both the key (string), and the associated Type of that key in order to give you Type safety. The thing is, it looks like you want to use a pure enum type where the isUserLoggedIn case doesn't have an associated Generic type. It wouldn't know if it's a bool, a string, integer or anything else.

However, there is no reason not to get creative. In my opinion, this ads way too much complexity, and you should stay away from it, but it is possible and helps to understand that you already have a clean solution at your hands by using DefaultsKit as is.

Check it out:

enum MyKeys<ValueType: Codable> {
    case isUserLoggedIn

    func save(value: Codable) {
        switch self {
        case .isUserLoggedIn:
            // DefaultsKit is supposed to give you strongly typed access to the UserDefaults. 
            // Force casting this, strips you of any safety. 
            // In other words, You'd be better of using Apple's UserDefaults directly.
            Defaults.shared.set(value as! Bool, for: Key<Bool>("isUserLoggedIn")) 
        }
    }

}

extension Defaults {
    func save<T>(value: T, someKey: MyKeys<T>) {
        someKey.save(value: value)
    }
}

And finally, you could do:

defaults.save(value: true, someKey: .isUserLoggedIn)

Now, that is only part of the solution. A horrible one, imo. If you were to read the value back, you would now need an associated type. That would require some more of that creativity... I would advise you not to do what you're trying to do.

Now, let's look at DefaultsKit api:

// This is perfectly acceptable
// It's clean, clear and easy to understand
// ...and it's safe!
defaults.set(true, forKey: Keys.isUserLoggedIn)

I'm honestly a bit tired, maybe you can come up with something more clever that I'm just not seeing.

Anyways, I hope that helped.

Cheers

toseefkhilji commented 6 years ago

Hi @nmdias ,

Thank you very much for your detailed explanation.

I also thinking of not to mess up all things. I'll go with my current implementation.

Thanks again.