[swift-evolution] NSCoding-like Persistence
Jonathan Hull
jhull at gbis.com
Thu Mar 24 20:30:15 CDT 2016
What is the current plan for persisting things like enums and structs in Swift?
After the POP talk at WWDC, I excitedly rewrote many of my frameworks to use protocols and structs/enums instead of NSObject subclasses. For the most part, this has been fantastic… most things are much more powerful/flexible using protocols and value types. The one problem I keep running into, however, is how to persist things in the same way you can with NSCoding. NSCoding requires NSObject as a base class.
I spent the last couple of weekends playing with ideas for a persistence framework and I was able to get about 90% of the way there. I was able to encode types like [(Int,Float)] by supplying closures to the encoding function. For example: func encodeArray<T>(array:[T], forKey:String, mapping:(T)->Encoding). There is a simpler version without the closure for arrays where T adheres to my “Encodable” protocol: func encodeArray<T:Encodable>(array:[T], forKey:String). I also have legacy support for objects which adhere to NSCoding.
Instead of going straight to data like NSCoding, I encode to an intermediate format (A struct with an internal enum). Then you have another protocol which can turn that format into data, json, plist, etc…
90% working, but I ran into a few problems. First, I have to use this horrible thing to get the type system to cooperate in some cases:
func horribleAutocastHack<T>(x:Any, fail:(()throws-> T)? = nil)throws -> T{
if let cast = x as? T{
return cast
}
if let fail = fail{
return try fail()
}
fatalError("Autocast failed")
}
Second, I had to use static methods instead of init in my protocol, since init fails on classes where I don’t have access to the code (e.g. NSData). It wants me to mark it both required and final, which I can’t do.
Third, I have no idea how to persist closures. It may just be flat out impossible. The big effect it has had is that anywhere where I had to build a thunk to store a collection of heterogeneous objects (adhering to a protocol with self requirements) it can no longer be persisted. This is actually the biggest issue, and I haven’t even been able to hack around it.
Finally, I am pushing the generics system pretty hard. My first version was randomly crashing the compiler so I had to pull back on that front (e.g. having encodeArray instead of just encode which infers the arrayness). All of the various discussions around factory methods are also relevant.
I was able to get the rest working though.
Is there an official plan which I am duplicating effort on? I would be happy to share my code (after a couple more iterations) if that would be helpful/inspiring. I would also be happy to just work on other things and wait for the official solution if there is one coming… I may have to wait for more powerful generics in any case.
I feel like this is one of those things that is impacting a lot of real world codebases, and delaying adoption of POP, value types, etc...
Thanks,
Jon
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160324/b074309b/attachment.html>
More information about the swift-evolution
mailing list