Nice!

The key is to have a non generic base class as storage for statics and a 
subclass for generic types… brilliant.
I am definitely going to try this one.

Vladimir’s solution is also a nice fact to know. The key point of the compile 
error message seems to be «  static __stored__ «  hence, with computed it works.

Thanks for the posting.

> Le 7 juil. 2017 à 15:54, Kim Burgestrand <k...@burgestrand.se> a écrit :
> 
> Here's yet another alternative. I read an article doing this very thing a 
> while back, it might be interesting to you: 
> http://radex.io/swift/nsuserdefaults/static/ 
> <http://radex.io/swift/nsuserdefaults/static/>. It makes the key type a class 
> instead, and inherits from a non-generic parent class to which it adds the 
> static properties.
> 
> The gist of it is roughly like this (although the article uses subscript, 
> which does not allow for a generic implementation so I use a get/set approach 
> here for brevity):
> 
> ```
> class DefaultsKeys {}
> final class DefaultsKey<T>: DefaultsKeys {
>     let value: String
> 
>     init(_ value: String) {
>         self.value = value
>     }
> }
> 
> extension UserDefaults {
>     func get<T>(_ key: DefaultsKey<T>) -> T? {
>         return object(forKey: key.value) as? T
>     }
> 
>     func set<T>(_ key: DefaultsKey<T>, to value: T) {
>         set(value, forKey: key.value)
>     }
> }
> 
> extension DefaultsKeys {
>     static let version = DefaultsKey<String>("version")
> }
> 
> let defaults = UserDefaults.standard
> defaults.set(.version, to: "1.0")
> let version = defaults.get(.version)
> print(version ?? "N/A")
> ```
> 
> On Fri, 7 Jul 2017 at 14:00 Vladimir.S via swift-users <swift-users@swift.org 
> <mailto:swift-users@swift.org>> wrote:
> 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@swift.org <mailto:swift-users@swift.org>
> > https://lists.swift.org/mailman/listinfo/swift-users 
> > <https://lists.swift.org/mailman/listinfo/swift-users>
> >
> _______________________________________________
> swift-users mailing list
> swift-users@swift.org <mailto:swift-users@swift.org>
> https://lists.swift.org/mailman/listinfo/swift-users 
> <https://lists.swift.org/mailman/listinfo/swift-users>

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

Reply via email to