<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Nice!<div class=""><br class=""></div><div class="">The key is to have a non generic base class as storage for statics and a subclass for generic types… brilliant.</div><div class="">I am definitely going to try this one.</div><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">Thanks for the posting.</div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">Le 7 juil. 2017 à 15:54, Kim Burgestrand <<a href="mailto:kim@burgestrand.se" class="">kim@burgestrand.se</a>> a écrit :</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class="">Here's yet another alternative. I read an article doing this very thing a while back, it might be interesting to you: <a href="http://radex.io/swift/nsuserdefaults/static/" class="">http://radex.io/swift/nsuserdefaults/static/</a>. It makes the key type a class instead, and inherits from a non-generic parent class to which it adds the static properties.</div><div class=""><br class=""></div><div class="">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):</div><div class=""><div class=""><br class=""></div><div class="">```</div><div class=""><div class=""><font face="monospace" class="">class DefaultsKeys {}</font></div><div class=""><font face="monospace" class="">final class DefaultsKey<T>: DefaultsKeys {</font></div><div class=""><font face="monospace" class=""> let value: String</font></div><div class=""><font face="monospace" class=""><br class=""></font></div><div class=""><font face="monospace" class=""> init(_ value: String) {</font></div><div class=""><font face="monospace" class=""> self.value = value</font></div><div class=""><font face="monospace" class=""> }</font></div><div class=""><font face="monospace" class="">}</font></div><div class=""><font face="monospace" class=""><br class=""></font></div><div class=""><font face="monospace" class="">extension UserDefaults {</font></div><div class=""><font face="monospace" class=""> func get<T>(_ key: DefaultsKey<T>) -> T? {</font></div><div class=""><font face="monospace" class=""> return object(forKey: key.value) as? T</font></div><div class=""><font face="monospace" class=""> }</font></div><div class=""><font face="monospace" class=""><br class=""></font></div><div class=""><font face="monospace" class=""> func set<T>(_ key: DefaultsKey<T>, to value: T) {</font></div><div class=""><font face="monospace" class=""> set(value, forKey: key.value)</font></div><div class=""><font face="monospace" class=""> }</font></div><div class=""><font face="monospace" class="">}</font></div><div class=""><font face="monospace" class=""><br class=""></font></div><div class=""><font face="monospace" class="">extension DefaultsKeys {</font></div><div class=""><font face="monospace" class=""> static let version = DefaultsKey<String>("version")</font></div><div class=""><font face="monospace" class="">}</font></div><div class=""><font face="monospace" class=""><br class=""></font></div><div class=""><font face="monospace" class="">let defaults = UserDefaults.standard</font></div><div class=""><font face="monospace" class="">defaults.set(.version, to: "1.0")</font></div><div class=""><font face="monospace" class="">let version = defaults.get(.version)</font></div><div class=""><font face="monospace" class="">print(version ?? "N/A")</font></div></div><div class="">```</div></div></div><br class=""><div class="gmail_quote"><div dir="ltr" class="">On Fri, 7 Jul 2017 at 14:00 Vladimir.S via swift-users <<a href="mailto:swift-users@swift.org" class="">swift-users@swift.org</a>> wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On 07.07.2017 14:02, Thierry Passeron via swift-users wrote:<br class="">
> Hi Everyone,<br class="">
><br class="">
> 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:<br class="">
<br class="">
The only kind of solution I was able to implement, is with calculated properties in<br class="">
extension. Hope this have any sense and most likely can be improved(code from swift<br class="">
sandbox):<br class="">
<br class="">
struct DefaultsKey<T> {<br class="">
var rawValue : String<br class="">
<br class="">
init(_ name: String) {<br class="">
rawValue = name<br class="">
}<br class="">
}<br class="">
<br class="">
extension DefaultsKey {<br class="">
static var version : DefaultsKey<String> { return DefaultsKey<String>("version") }<br class="">
static var code : DefaultsKey<Int> { return DefaultsKey<Int>("code") }<br class="">
}<br class="">
<br class="">
func UserDefaults_standard_object(forKey: String) -> Any? {<br class="">
switch forKey {<br class="">
case "version" : return "1.0.0"<br class="">
case "code" : return 12345<br class="">
default : return nil<br class="">
}<br class="">
}<br class="">
<br class="">
func Defaults<T>(_ key: DefaultsKey<T>) -> T? {<br class="">
return UserDefaults_standard_object(forKey: key.rawValue) as? T<br class="">
}<br class="">
<br class="">
let version = Defaults(.version)<br class="">
let code = Defaults(.code)<br class="">
<br class="">
print(version ?? "-no value-", type(of: version)) // 1.0.0 Optional<String><br class="">
print(code ?? "-no value-", type(of: code)) // 12345 Optional<Int><br class="">
<br class="">
<br class="">
<br class="">
><br class="">
> public struct DefaultsKey: RawRepresentable, Equatable, Hashable, Comparable {<br class="">
><br class="">
> public var rawValue: String<br class="">
> public var hashValue: Int { return rawValue.hash }<br class="">
><br class="">
> public init(_ rawValue: String) { self.rawValue = rawValue }<br class="">
> public init(rawValue: String) { self.rawValue = rawValue }<br class="">
><br class="">
> /* Protocols implementation .. */<br class="">
> }<br class="">
><br class="">
> Now I can make extensions like:<br class="">
><br class="">
> extension DefaultsKey {<br class="">
> static let version = DefaultsKey("version »)<br class="">
> }<br class="">
><br class="">
> And use it to query the UserDefaults.<br class="">
><br class="">
> public func Defaults<T>(_ key: DefaultsKey) -> T? {<br class="">
> return UserDefaults.standard.object(forKey: key.rawValue) as? T<br class="">
> }<br class="">
><br class="">
> let version: String? = Defaults(.version)<br class="">
><br class="">
> Nice, concise, I love it…<br class="">
><br class="">
> 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:<br class="">
><br class="">
> public struct DefaultsKey<T>: RawRepresentable, Equatable, Hashable, Comparable {<br class="">
> …<br class="">
> }<br class="">
><br class="">
> extension DefaultsKey {<br class="">
> static let version = DefaultsKey<String>("version »)<br class="">
> }<br class="">
><br class="">
> But this doesn’t compile:<br class="">
> error: static stored properties not supported in generic types<br class="">
><br class="">
> I guess I could keep all the keys outside an extension scope but then it would not be as concise as with Notification.Name<br class="">
><br class="">
> Please let me know if there is indeed a generic way to solve this. Any help would be greatly appreciated.<br class="">
> Thanks in advance.<br class="">
><br class="">
> Thierry.<br class="">
> _______________________________________________<br class="">
> swift-users mailing list<br class="">
> <a href="mailto:swift-users@swift.org" target="_blank" class="">swift-users@swift.org</a><br class="">
> <a href="https://lists.swift.org/mailman/listinfo/swift-users" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-users</a><br class="">
><br class="">
_______________________________________________<br class="">
swift-users mailing list<br class="">
<a href="mailto:swift-users@swift.org" target="_blank" class="">swift-users@swift.org</a><br class="">
<a href="https://lists.swift.org/mailman/listinfo/swift-users" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-users</a><br class="">
</blockquote></div>
</div></blockquote></div><br class=""></div></body></html>