Trying out SwiftData: Cool Concepts, But Probably Not Ready Yet
Apple did not only announce interesting new products, it also released a lot of good stuff for developers at WWDC 2023. Especially SwiftUI, Apple's modern, declarative UI framework, gained many practical new additions that we will already use in Firetask 5, the next generation of our GTDĀ® task management app. Examples include a focus management system that now works as you would expect it for iPad and Mac and a number of scroll view improvements that many developers have been waiting for for some time.
But the most interesting thing was probably a new Swift framework, namely SwiftData: a "swifty" wrapper around Core Data that should make persisting information between app launches a lot easier.
"SwiftData is a powerful framework for data modelling and management and enhances your modern Swift app. Like SwiftUI, it focuses entirely on code with no external file formats and uses Swift's new macro system to create a seamless API experience." [Ben Trumbull introducing SwiftData at WWDC 2023]
SwiftData has so many really cool concepts which meant I simply had to try it out to see what it can already do (and what not).
[Disclaimer: You might want to skip to the conclusion below if you are not a technical person, or do not know anything about Core Data... :-]
So, what did I like about SwiftData? What works really well?
- First of all, SwiftData has very clean, practical and straightforward APIs
- All schema definition is done in code using attached macros
- SwiftData's "ModelContainer" is even easier to set up than NSPersistentContainer -- and history tracking is always enabled
- Persistent objects can be created without a context
- Automatic tracking of changes works really nicely with the new SwiftUI observation concepts
- All query predicates are typed and are created using a simple, but powerful predicate builder
- The SwiftUI query integration feels even more natural than for Core Data fetch results -- although I did not see a way yet to create a sectioned fetch (which I could have missed, or it could still arrive in a later beta)
OK, but there are always some strings attached. So what does not work [yet]? What kind of limitations are there that will most likely also not go away in the first production version later this year?
- There is no easy way to react to lifecycle events per object
- I did not find a way to specify an index for an attribute
- No explicit support for child contexts -- although maybe not needed anymore, as you can create objects outside of a context
- No support for derived attributes
- It seems also no support for ordered collections -- at least arrays do not preserve their order, but behave more like sets (which is OK for me, I like to implement these things myself and it does not work anyway with CloudKit syncing)
- It is unclear how to do explicit history tracking using ModelContainer, e.g., for communicating with app extensions
- Finally, CoreSpotlight integration is there, but seems to be not really usable yet
Bottomline: SwiftData in its very first version is definitely more complete than SwiftUI when it was introduced -- which is not surprising, as SwiftData is only a wrapper around CoreData rather than a whole new framework based on totally new concepts. However, maybe comparable to SwiftUI two years ago, SwiftData (in its current state) is lacking many important ingredients for building larger, more complex applications. You can maybe already use it for simple apps, but I would be very careful.
We would have really loved to use SwiftData already for Firetask 5, but the risk is too high and the framework is simply not ready yet. Besides lacking vital functionality, a lot of things are still unclear, detailed documentation is very limited (as always at this stage, let's hope it gets better -- it not always does unfortunately...) and especially interaction with CloudKit for more complex use cases (e.g., deduplication) seems to be problematic.
"There is the risk you cannot afford to take, and there is the risk you cannot afford not to take." [Peter Drucker]
But it also felt wrong to do nothing, as SwiftData is really great from a conceptual point of view, so we voted for writing a very thin layer that feels already a bit like SwiftData, but simply wraps our current Core Data infrastructure. We hope that this will help us writing more maintainable code and save us work in the long run when we will be able to adopt SwiftData in a couple of years from now ;-).