<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 « &nbsp;static __stored__ « &nbsp;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 &lt;<a href="mailto:kim@burgestrand.se" class="">kim@burgestrand.se</a>&gt; 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:&nbsp;<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&lt;T&gt;: DefaultsKeys {</font></div><div class=""><font face="monospace" class="">&nbsp; &nbsp; let value: String</font></div><div class=""><font face="monospace" class=""><br class=""></font></div><div class=""><font face="monospace" class="">&nbsp; &nbsp; init(_ value: String) {</font></div><div class=""><font face="monospace" class="">&nbsp; &nbsp; &nbsp; &nbsp; self.value = value</font></div><div class=""><font face="monospace" class="">&nbsp; &nbsp; }</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="">&nbsp; &nbsp; func get&lt;T&gt;(_ key: DefaultsKey&lt;T&gt;) -&gt; T? {</font></div><div class=""><font face="monospace" class="">&nbsp; &nbsp; &nbsp; &nbsp; return object(forKey: key.value) as? T</font></div><div class=""><font face="monospace" class="">&nbsp; &nbsp; }</font></div><div class=""><font face="monospace" class=""><br class=""></font></div><div class=""><font face="monospace" class="">&nbsp; &nbsp; func set&lt;T&gt;(_ key: DefaultsKey&lt;T&gt;, to value: T) {</font></div><div class=""><font face="monospace" class="">&nbsp; &nbsp; &nbsp; &nbsp; set(value, forKey: key.value)</font></div><div class=""><font face="monospace" class="">&nbsp; &nbsp; }</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="">&nbsp; &nbsp; static let version = DefaultsKey&lt;String&gt;("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 &lt;<a href="mailto:swift-users@swift.org" class="">swift-users@swift.org</a>&gt; 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="">
&gt; Hi Everyone,<br class="">
&gt;<br class="">
&gt; 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&lt;T&gt; {<br class="">
&nbsp; &nbsp; &nbsp; &nbsp; var rawValue : String<br class="">
<br class="">
&nbsp; &nbsp; &nbsp; &nbsp; init(_ name: String) {<br class="">
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rawValue = name<br class="">
&nbsp; &nbsp; &nbsp; &nbsp; }<br class="">
}<br class="">
<br class="">
extension DefaultsKey {<br class="">
&nbsp; &nbsp; &nbsp; &nbsp; static var version : DefaultsKey&lt;String&gt; { return DefaultsKey&lt;String&gt;("version") }<br class="">
&nbsp; &nbsp; &nbsp; &nbsp; static var code : DefaultsKey&lt;Int&gt; { return DefaultsKey&lt;Int&gt;("code") }<br class="">
}<br class="">
<br class="">
func UserDefaults_standard_object(forKey: String) -&gt; Any? {<br class="">
&nbsp; &nbsp; &nbsp; &nbsp; switch forKey {<br class="">
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case "version" : return "1.0.0"<br class="">
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case "code" : return 12345<br class="">
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; default : return nil<br class="">
&nbsp; &nbsp; &nbsp; &nbsp; }<br class="">
}<br class="">
<br class="">
func Defaults&lt;T&gt;(_ key: DefaultsKey&lt;T&gt;) -&gt; T? {<br class="">
&nbsp; &nbsp;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&lt;String&gt;<br class="">
print(code ?? "-no value-", type(of: code))&nbsp; &nbsp; &nbsp; &nbsp;// 12345 Optional&lt;Int&gt;<br class="">
<br class="">
<br class="">
<br class="">
&gt;<br class="">
&gt; public struct DefaultsKey: RawRepresentable, Equatable, Hashable, Comparable {<br class="">
&gt;<br class="">
&gt;&nbsp; &nbsp; public var rawValue: String<br class="">
&gt;&nbsp; &nbsp; public var hashValue: Int { return rawValue.hash }<br class="">
&gt;<br class="">
&gt;&nbsp; &nbsp; public init(_ rawValue: String) { self.rawValue = rawValue }<br class="">
&gt;&nbsp; &nbsp; public init(rawValue: String) { self.rawValue = rawValue }<br class="">
&gt;<br class="">
&gt;&nbsp; &nbsp; /* Protocols implementation .. */<br class="">
&gt; }<br class="">
&gt;<br class="">
&gt; Now I can make extensions like:<br class="">
&gt;<br class="">
&gt; extension DefaultsKey {<br class="">
&gt;&nbsp; &nbsp; static let version = DefaultsKey("version »)<br class="">
&gt; }<br class="">
&gt;<br class="">
&gt; And use it to query the UserDefaults.<br class="">
&gt;<br class="">
&gt; public func Defaults&lt;T&gt;(_ key: DefaultsKey) -&gt; T? {<br class="">
&gt;&nbsp; &nbsp; return UserDefaults.standard.object(forKey: key.rawValue) as? T<br class="">
&gt; }<br class="">
&gt;<br class="">
&gt; let version: String? = Defaults(.version)<br class="">
&gt;<br class="">
&gt; Nice, concise, I love it…<br class="">
&gt;<br class="">
&gt; 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="">
&gt;<br class="">
&gt; public struct DefaultsKey&lt;T&gt;: RawRepresentable, Equatable, Hashable, Comparable {<br class="">
&gt; …<br class="">
&gt; }<br class="">
&gt;<br class="">
&gt; extension DefaultsKey {<br class="">
&gt;&nbsp; &nbsp; static let version = DefaultsKey&lt;String&gt;("version »)<br class="">
&gt; }<br class="">
&gt;<br class="">
&gt; But this doesn’t compile:<br class="">
&gt;&nbsp; &nbsp; &nbsp;error: static stored properties not supported in generic types<br class="">
&gt;<br class="">
&gt; 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="">
&gt;<br class="">
&gt; Please let me know if there is indeed a generic way to solve this. Any help would be greatly appreciated.<br class="">
&gt; Thanks in advance.<br class="">
&gt;<br class="">
&gt; Thierry.<br class="">
&gt; _______________________________________________<br class="">
&gt; swift-users mailing list<br class="">
&gt; <a href="mailto:swift-users@swift.org" target="_blank" class="">swift-users@swift.org</a><br class="">
&gt; <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="">
&gt;<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>