[swift-users] UserDefaults with generic keys

Vladimir.S svabox at gmail.com
Fri Jul 7 07:00:09 CDT 2017


On 07.07.2017 14:02, Thierry Passeron via swift-users wrote:
> Hi Everyone,
> 
> Using Swift 3.1, I was wondering if I could come up with something largely inspired by Notification.Name to help me deal with UserDefaults so I started by doing something like:

The only kind of solution I was able to implement, is with calculated properties in 
extension. Hope this have any sense and most likely can be improved(code from swift 
sandbox):

struct DefaultsKey<T> {
	var rawValue : String
	
	init(_ name: String) {
		rawValue = name
	}
}

extension DefaultsKey {
	static var version : DefaultsKey<String> { return DefaultsKey<String>("version") }
	static var code : DefaultsKey<Int> { return DefaultsKey<Int>("code") }
}

func UserDefaults_standard_object(forKey: String) -> Any? {
	switch forKey {
		case "version" : return "1.0.0"
		case "code" : return 12345
		default : return nil
	}
}

func Defaults<T>(_ key: DefaultsKey<T>) -> T? {
   return UserDefaults_standard_object(forKey: key.rawValue) as? T
}

let version = Defaults(.version)
let code = Defaults(.code)

print(version ?? "-no value-", type(of: version)) // 1.0.0 Optional<String>
print(code ?? "-no value-", type(of: code))       // 12345 Optional<Int>



> 
> public struct DefaultsKey: RawRepresentable, Equatable, Hashable, Comparable {
>    
>    public var rawValue: String
>    public var hashValue: Int { return rawValue.hash }
>    
>    public init(_ rawValue: String) { self.rawValue = rawValue }
>    public init(rawValue: String) { self.rawValue = rawValue }
>    
>    /* Protocols implementation .. */
> }
> 
> Now I can make extensions like:
> 
> extension DefaultsKey {
>    static let version = DefaultsKey("version »)
> }
> 
> And use it to query the UserDefaults.
> 
> public func Defaults<T>(_ key: DefaultsKey) -> T? {
>    return UserDefaults.standard.object(forKey: key.rawValue) as? T
> }
> 
> let version: String? = Defaults(.version)
> 
> Nice, concise, I love it…
> 
> But It could be even better to let the compiler check the return type of the UserDefault for the DefaultKey that I ask if only I could create the key and bind it to a type. So I tried this:
> 
> public struct DefaultsKey<T>: RawRepresentable, Equatable, Hashable, Comparable {
>> }
> 
> extension DefaultsKey {
>    static let version = DefaultsKey<String>("version »)
> }
> 
> But this doesn’t compile:
>     error: static stored properties not supported in generic types
> 
> I guess I could keep all the keys outside an extension scope but then it would not be as concise as with Notification.Name
> 
> Please let me know if there is indeed a generic way to solve this. Any help would be greatly appreciated.
> Thanks in advance.
> 
> Thierry.
> _______________________________________________
> swift-users mailing list
> swift-users at swift.org
> https://lists.swift.org/mailman/listinfo/swift-users
> 


More information about the swift-users mailing list