{"id":39698,"date":"2023-06-12T14:18:18","date_gmt":"2023-06-12T18:18:18","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=39698"},"modified":"2023-09-14T08:22:05","modified_gmt":"2023-09-14T12:22:05","slug":"swiftdata","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2023\/06\/12\/swiftdata\/","title":{"rendered":"SwiftData"},"content":{"rendered":"<p><a href=\"https:\/\/developer.apple.com\/documentation\/SwiftData\">Apple<\/a> (<a href=\"https:\/\/news.ycombinator.com\/item?id=36215357\">Hacker News<\/a>):<\/p>\n<blockquote cite=\"https:\/\/developer.apple.com\/documentation\/SwiftData\">\n<p>Combining Core Data&rsquo;s proven persistence technology and Swift&rsquo;s modern concurrency features, SwiftData enables you to add persistence to your app quickly, with minimal code and no external dependencies. Using modern language features like macros, SwiftData enables you to write code that is fast, efficient, and safe, enabling you to describe the entire model layer (or object graph) for your app. The framework handles storing the underlying model data, and optionally, syncing that data across multiple devices.<\/p>\n<\/blockquote>\n<p>We&rsquo;ve been anticipating this for years, and it finally happened. Apple was waiting until it could utilize Swift Concurrency and macros, and I think that was a good decision. As <a href=\"https:\/\/drewmccormack.medium.com\/here-is-what-swiftdata-will-be-and-what-it-could-have-been-65b79cd11c6a\">expected<\/a>, it&rsquo;s more a Core Data wrapper than a complete reimagining. This is making some people unhappy, but I think the underlying Core Data design is still pretty solid. Perhaps over time Apple will reimplement the back end, as they are doing with Foundation. I&rsquo;d certainly like to see less overhead at the managed object level, and database operations should be able to go a lot faster if they can work directly with Swift&rsquo;s UTF-8 strings.<\/p>\n<p>Since it requires Sonoma, and the initial version is completely inadequate for my needs, SwiftData probably won&rsquo;t show up in my own code for years. But I&rsquo;m pleased to see that Apple is moving in the same direction as I&rsquo;ve been doing with my own Core Data code: schemas defined in code, type-safe predicates, a <code>Collection<\/code> for batch processing, and migrations decomposed into stages of lightweight table alterations with interleaved fixups.<\/p>\n<p>I was excited to see that there were <em>five<\/em> WWDC sessions about SwiftData, but it turns out that they were rather short, repetitive, and lacking in depth. Apple seems to have deliberately avoided comparing it to Core Data and giving us a map of what&rsquo;s different vs. the same and what&rsquo;s not supported (yet?). So here are some things that I found notable and some questions that were unanswered:<\/p>\n<p>Just about everything was renamed. In some cases this makes sense. For example, I never really understood why we had <code>NSEntityDescription<\/code> instead of just <code>NSEntity<\/code>. Now it&rsquo;s <code><a href=\"https:\/\/developer.apple.com\/documentation\/swiftdata\/entity\">Entity<\/a><\/code>. In other cases, it&rsquo;s a bit confusing because <code>NSManagedObject<\/code> has become <code>PersistentModel<\/code>, whereas &ldquo;model&rdquo; used to mean something completely different that is now called <code>Schema<\/code>. &ldquo;Transient&rdquo; was not renamed but its meaning has changed. There&rsquo;s no more store coordinator and no replacement for some of its functionality.<\/p>\n<p>The XML and binary store types are gone. I&rsquo;m guessing that the memory store is now based on SQLite, though I don&rsquo;t think Apple has said.<\/p>\n<p>It sounds like <code><a href=\"https:\/\/developer.apple.com\/documentation\/foundation\/predicate\">Predicate<\/a><\/code> does not yet support everything that <code>NSPredicate<\/code> did, but it&rsquo;s not clear to me exactly what the differences are or to what extent you can use <code>NSPredicate<\/code> from SwiftData. I guess a lot of questions can probably be answered from <a href=\"https:\/\/github.com\/apple\/swift-foundation\/tree\/main\/Sources\/FoundationEssentials\/Predicate\">the code<\/a>.<\/p>\n<p>Likewise with various schema features. I didn&rsquo;t see anything about indexes or validation predicates. Having <code>.unique<\/code> just do an <code>UPSERT<\/code> when there&rsquo;s a conflict is kind of cool, but what if I want to handle constraint violations in a different way? Composite uniqueness constraints still seem to be handled as arrays of strings. If you want to include components of a composite attribute, I guess you&rsquo;re supposed to use the <code>mangledName<\/code>?<\/p>\n<p>How do <code><a href=\"https:\/\/developer.apple.com\/documentation\/swiftdata\/persistentidentifier\">PersistentIdentifier<\/a><\/code>s work? I don&rsquo;t see a way to convert it back and forth to <code>NSManagedObjectID<\/code> or <code>URL<\/code>, which seems like a major problem. There also doesn&rsquo;t seem to be the concept of a temporary identifier. Temporary IDs were a major source of bugs with Core Data, but I don&rsquo;t see how they could have been eliminated without causing major performance problems. If they are still there but opaque to us, that seems bad.<\/p>\n<p><code><a href=\"https:\/\/developer.apple.com\/documentation\/swiftdata\/persistentmodel\">PersistentModel<\/a><\/code> seems to be missing a lot of lifecycle hooks and control over faulting and refreshing. I was surprised to see that relationships are handled as arrays instead of as sets, even though presumably they are still sets at the database level. There does not seem to be support for ordered relationships. Built-in support for non-object attribute types is great. For structs and enums, it&rsquo;s not fully clear to me when they get automatically destructured into composite attributes, when it just uses <code>Codable<\/code> to transform them into a blob of data, and whether I can choose.<\/p>\n<p>Stuff at the context level is more automatic and gives you less control. Auto-saving that can be turned off is nice. But there doesn&rsquo;t seem to be a way to set a merge policy between the context and store, and I didn&rsquo;t see anything about merging changes between contexts. There are also no more parent contexts.<\/p>\n<p>There&rsquo;s no <code>ModelStore<\/code> class, just <code>ModelContainer<\/code> and <code>ModelContext<\/code>. I guess containers can still have multiple stores because they support a <code>configurations<\/code> array, but I&rsquo;m not sure whether you can add to this. There doesn&rsquo;t seem to be a way to assign the store for a new object, nor to scope a fetch to certain stores.<\/p>\n<p>Persistent history tracking is enabled by default, but you can seemingly only access the history via Core Data.<\/p>\n<p>Contexts now have much more convenient APIs for batch enumeration (with mutation checking!) and batch inserts\/deletes\/updates. The batch insert API seems less efficient, though, since you have to give it fully realized Swift dictionaries (no shared keys or provider). There does not seem to be a way to do count or dictionary fetches.<\/p>\n<p>Lastly, SwiftData was clearly designed to work with Swift Concurrency, but Apple didn&rsquo;t say much about this. I assume the idea is that the language will prevent you from passing model objects out of their context&rsquo;s actor&mdash;but <a href=\"https:\/\/mastodon.social\/@calicoding\/110494798403226191\">maybe not<\/a>.<\/p>\n\n<p>See also:<\/p>\n<ul>\n<li><a href=\"https:\/\/michaelrowe01.com\/index.php\/blog\/whats-new-in-core-data\/\">Michael Rowe<\/a><\/li>\n<li><a href=\"https:\/\/mastodon.social\/@calicoding\/110494798403226191\">CaliCoding<\/a><\/li>\n<li><a href=\"https:\/\/www.donnywals.com\/newsletters\/IjFfi58mg13HlfPKrTwdzw\/\">Donny Wals<\/a><\/li>\n<li><a href=\"https:\/\/www.infoq.com\/news\/2023\/06\/swiftdata-persistent-framework\/\">Sergio De Simone<\/a><\/li>\n<\/ul>\n\n<p>Previously:<\/p>\n<ul>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2023\/06\/06\/wwdc-2023-links\/\">WWDC 2023 Links<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2023\/04\/27\/swift-foundation-preview\/\">Swift Foundation Preview<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2023\/02\/03\/designing-swifts-macros-feature\/\">Designing Swift&rsquo;s Macros Feature<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2022\/12\/13\/swift-pitch-predicates\/\">Swift Pitch: Predicates<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2022\/08\/26\/lighter-swift\/\">Lighter.swift<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2021\/03\/31\/making-nsfetchrequest-fetchbatchsize-work-with-swift\/\">Making NSFetchRequest.fetchBatchSize Work With Swift<\/a><\/li>\n<\/ul>\n\n<p id=\"swiftdata-update-2023-06-13\">Update (2023-06-13): <a href=\"https:\/\/mastodon.social\/@mynameisstuart\/110533424434477270\">Stuart Breckenridge<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@mynameisstuart\/110533424434477270\">\n<p>There&rsquo;s no way to turn off write-ahead logging in SwiftData.<\/p>\n<\/blockquote>\n<p>Indeed, there doesn&rsquo;t seem to be access to any of the coordinator options or SQLite pragmas.<\/p>\n\n<p><a href=\"https:\/\/mastodon.social\/@groue@hachyderm.io\/110519343357931563\">Gwendal Rou&eacute;<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@groue@hachyderm.io\/110519343357931563\"><p>So&#8230; one WWDC video mentions that SwiftData performs upserts when there is a conflict on an unique attribute. Corollary: SwiftData does not perform uniquing, at least not like Core Data, and we may end up with two distinct model instances that refer to the same persisted database row. &ldquo;Identity&rdquo; of models promises to be a subtle source of surprises &#x1F605;<\/p><\/blockquote>\n<p>I&rsquo;m <a href=\"https:\/\/mastodon.social\/@mjtsai\/110533304537837221\">guessing<\/a> that it will do the same thing as Core Data and give you a <a href=\"https:\/\/mastodon.social\/@mjtsai\/110534353825407001\">detached<\/a> object with a different ID. That still seems to be possible to detect because <code>PersistentModel.context<\/code> is optional. But it would be good for Apple to explain this.<\/p>\n\n<p><a href=\"https:\/\/mastodon.social\/@palevich\/110522651809127758\">Jack Palevich<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@palevich\/110522651809127758\"><p>I wish Apple would publish a &ldquo;theory of operation&rdquo; for both CoreData and SwiftData, that documents and explains the design choices they have made.<\/p><p>There are a lot of subtle tradeoffs when designing an ORM. When you see something like this upsert\/uniquing tradeoff, it would be nice to know if it&rsquo;s an intentional tradeoff, and if so, what the motivations is.<\/p><\/blockquote>\n\n<p id=\"swiftdata-update-2023-06-19\">Update (2023-06-19): <a href=\"https:\/\/mastodon.social\/@samalone@twit.social\/110527350587954967\">Stuart A. Malone<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@samalone@twit.social\/110527350587954967\"><p>This was the first error I encountered using Swift Data, too. I don&rsquo;t have the code in front of me, but I believe I solved it by inserting both objects in the relationship into the context before creating the relationship. It didn&rsquo;t like having an object in a context related to an object without a context.<\/p><\/blockquote>\n<p>With Core Data, new objects are <a href=\"https:\/\/mastodon.social\/@mjtsai\/110568260380535651\">inserted into a context<\/a> by default.<\/p>\n\n<p><a href=\"https:\/\/mastodon.social\/@helge\/110568086456012051\">Helge He&szlig;<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@helge\/110568086456012051\">\n<p>OMG, a 10k batch size did it. It took 4 hours and peeked at over 70GB of RAM usage, but SwiftData finally managed to import my huge 25MB SQLite database &#x1F642;<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/useyourloaf.com\/blog\/wwdc23-swiftdata-lab-notes\/\">Keith Harrison<\/a>:<\/p>\n<blockquote cite=\"https:\/\/useyourloaf.com\/blog\/wwdc23-swiftdata-lab-notes\/\">\n<p>I attended a WWDC23 SwiftData lab and asked questions in the data-frameworks Slack QA session. This is my summary of what I learned.<\/p>\n<\/blockquote>\n\n<p id=\"swiftdata-update-2023-06-21\">Update (2023-06-21): <a href=\"https:\/\/developer.apple.com\/forums\/thread\/731483\">milutz<\/a>:<\/p>\n<blockquote cite=\"https:\/\/developer.apple.com\/forums\/thread\/731483\">\n<p>Nevertheless, if I have a unique constraint on an (String) attribute and try to insert the same again, I end up in the debugger in the generated getter of the attribute[&#8230;]<\/p>\n<\/blockquote>\n\n<p id=\"swiftdata-update-2023-06-23\">Update (2023-06-23): <a href=\"https:\/\/mastodon.social\/@twostraws\/110588369908379410\">Paul Hudson<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@twostraws\/110588369908379410\"><p>I just filed a whole bunch of feedback reports for Apple regarding SwiftData. If you see any of these and want the same, please file your own report asking for it &#x2013; every feedback counts, particularly now as we&rsquo;re still in the early betas.<\/p><\/blockquote>\n\n<p id=\"swiftdata-update-2023-06-26\">Update (2023-06-26): <a href=\"https:\/\/mastodon.social\/@helge\/110610681288203048\">Helge He&szlig;<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@helge\/110610681288203048\"><p>There is no way to do a case-insensitive compare\/contains in SwiftData predicates yet, right? It tried a few things, but they don&rsquo;t seem to work.<\/p><\/blockquote>\n<p>Nor normalized comparisons.<\/p>\n\n<p id=\"swiftdata-update-2023-06-30\">Update (2023-06-30): <a href=\"https:\/\/mastodon.social\/@helge\/110616683697639042\">Helge He&szlig;<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@helge\/110616683697639042\"><p>The <code>Predicate<\/code> macro as used in  gave me a bit of a head scratch, but I think I have figured it out.\nThe <code>init<\/code> of the <code>Predicate<\/code> struct takes a <code>builder<\/code> function, which gets a <code>Variable<\/code> as the input. Really just a placeholder. But it has to have a <code>VariableID<\/code>, that is picked by the <code>Variable.init<\/code> internally. Currently a <code>UInt<\/code> sequence.<\/p><\/blockquote>\n\n<p><a href=\"https:\/\/mastodon.social\/@helge\/110629801989655056\">Helge He&szlig;<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@helge\/110629801989655056\">\n<p>Here are the overloads required to get <code>Codable<\/code> SwiftData models. [Update (2023-09-08): <a href=\"https:\/\/hachyderm.io\/@helge@mastodon.social\/111024328355372109\">No longer needed<\/a>.]<\/p>\n<\/blockquote>\n\n<p id=\"swiftdata-update-2023-07-05\">Update (2023-07-05): <a href=\"https:\/\/azamsharp.com\/2023\/07\/04\/the-ultimate-swift-data-guide.html\">Mohammad Azam<\/a>:<\/p>\n<blockquote cite=\"https:\/\/azamsharp.com\/2023\/07\/04\/the-ultimate-swift-data-guide.html\">\n<p>This article is structured into several sections, each delving into different aspects of the SwiftData framework. First, we will explore the foundational concepts of SwiftData, followed by an examination of its architectural design, relationship management, migration capabilities, and more.<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/mastodon.social\/@twostraws\/110660720931214682\">Paul Hudson<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@twostraws\/110660720931214682\"><p>It&rsquo;s not long until the window closes for SwiftData changes in iOS 17.0. Please file feedback for things that affect you! Two massive ones for me: an equivalent of <code>NSFetchedResultsController<\/code> to make MVVM work, and an equivalent of (or at least support for) <code>NSCompoundPredicate<\/code>.<\/p><\/blockquote>\n\n<p><a href=\"https:\/\/mastodon.social\/@iandundas@mastodon.world\/110660944146158334\">Ian Dundas<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@iandundas@mastodon.world\/110660944146158334\"><p>1: <code>PersistentIdentifier<\/code> <a href=\"https:\/\/mastodon.world\/@iandundas\/110660567952047230\">encodes to blank JSON<\/a>, and 2: when it fails to migrate it doesn&rsquo;t just throw an error - it also wipes the database and starts fresh!!<\/p><\/blockquote>\n\n<p><a href=\"https:\/\/mastodon.social\/@helge\/110661612547055942\">Helge He&szlig;<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@helge\/110661612547055942\"><p>Looks like using a <code>DateComponents<\/code> value for like say a <code>birthDate<\/code> doesn&rsquo;t work in SwiftData. It fails already in the <code>Schema<\/code> setup (hence can&rsquo;t be worked around using an accessor extension for the <code>PersistentModel<\/code> like <code>Codable<\/code>).<\/p><\/blockquote>\n\n<p id=\"swiftdata-update-2023-07-10\">Update (2023-07-10): <a href=\"https:\/\/iosdev.space\/@StewartLynch\/110679290403099752\">Stewart Lynch<\/a>:<\/p>\n<blockquote cite=\"https:\/\/iosdev.space\/@StewartLynch\/110679290403099752\"><p>In SwiftData, if I create a model that has a property that is an enum like the following, what it does is create a property for each case of the enum rather than a single case for the property itself.\n<\/p><\/blockquote>\n\n<p><a href=\"https:\/\/mastodon.social\/@helge\/110678064592226014\">Helge He&szlig;<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@helge\/110678064592226014\">\n<p>Is it possible to undo changes to a SwiftData model object \/ view context? I would have thought that <code>modelContext.rollback()<\/code> would do that (as a peer to <code>save()<\/code>), but maybe that's for transactions only?<\/p>\n<\/blockquote>\n<p>I&rsquo;m quite surprised to hear that <code>rollback()<\/code> does not work like with Core Data. There&rsquo;s no documentation yet about what it&rsquo;s intended to do.<\/p>\n\n<p><a href=\"https:\/\/itnext.io\/wwdc-23-first-impressions-of-swiftui-5-and-swiftdata-85d16df77e2c\">fatbobman<\/a>:<\/p>\n<blockquote cite=\"https:\/\/itnext.io\/wwdc-23-first-impressions-of-swiftui-5-and-swiftdata-85d16df77e2c\"><p>Here are some questions and considerations I have compiled regarding SwiftData (originally posted in a <a href=\"https:\/\/twitter.com\/fatbobman\/status\/1666639982247968769\">tweet<\/a>, without a more systematic categorization)[&#8230;]<\/p><p>[&#8230;]<\/p><p>In the current version, data created through other contexts (<code>ModelContext<\/code>) is not automatically merged into the view context.<\/p><p>[&#8230;]<\/p><p>Neither <code>PersistentModel<\/code> nor <code>ModelContext<\/code> are <code>Sendable<\/code> (<code>ModelContainer<\/code> is <code>Sendable<\/code>), and they are thread-limited like Core Data.<\/p><p>[&#8230;]<\/p><p>Derived options for <code>Attribute<\/code> have been deprecated.<\/p><\/blockquote><p>Is this referring to <a href=\"https:\/\/developer.apple.com\/documentation\/coredata\/nsderivedattributedescription\">NSDerivedAttributeDescription<\/a>?<\/p>\n\n<p>Via <a href=\"https:\/\/twitter.com\/malhal\/status\/1669776801361526797\">Malcolm Hall<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/malhal\/status\/1669776801361526797\"><p>&ldquo;<code>Query<\/code> (an alternative to <code>FetchRequest<\/code>) does not provide a method for dynamically switching predicates and sorting.&rdquo; crazy it was released with out this!<\/p><\/blockquote>\n\n<p><a href=\"https:\/\/twitter.com\/malhal\/status\/1668572385929248768\">Malcolm Hall<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/malhal\/status\/1668572385929248768\"><p><code>Query<\/code> for a relationship doesn&rsquo;t auto-update yet!<\/p><\/blockquote>\n\n<p id=\"swiftdata-update-2023-07-25\">Update (2023-07-25): <a href=\"https:\/\/mastodon.world\/@iandundas\/110739454510328391\">Ian Dundas<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.world\/@iandundas\/110739454510328391\">\n<p>Macro magic - expanding it shows that I guess a schema is defined with a default value would only be evaluated once. I guess the way around this is set the random values inside the <code>init(name:)<\/code>.<\/p>\n<\/blockquote>\n\n<p>In other words, because of the <code>@Model<\/code> macro, initial property values (which become default values in the schema) don&rsquo;t behave the same way as with a regular class, even though they look the same.<\/p>\n\n<p><a href=\"https:\/\/forums.swift.org\/t\/why-does-a-swiftdata-model-allow-array-how-do-you-really-store-one\/66257\">Jessy<\/a>:<\/p>\n<blockquote cite=\"https:\/\/forums.swift.org\/t\/why-does-a-swiftdata-model-allow-array-how-do-you-really-store-one\/66257\"><p>Why does a SwiftData <code>Model<\/code> allow <code>Array<\/code>? How do you really store one?<\/p><p>Order is not preserved, meaning the <code>Array<\/code> that exists in memory is not likely the one that will get persisted and reloaded. That&rsquo;s not really conceptually an <code>Array<\/code>&mdash;that&rsquo;s halfway to a <code>Set<\/code>.<\/p><\/blockquote>\n\n<p><a href=\"https:\/\/mastodon.social\/@helge\/110771711644283146\">Helge He&szlig;<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@helge\/110771711644283146\"><p>Maybe it is just me, but I just don&rsquo;t find much &ldquo;Swiftyness&rdquo; in SwiftData. In fact it doesn&rsquo;t feel Swifty at all to me. Well, maybe when that <code>#Predicate<\/code> with 3 expressions gets back to you with the &ldquo;unable to resolve blub in time&rdquo; &#x1F648;<\/p><p>E.g. Swiftlang has gone (extraordinarily annoying) lengths at making sure that the initialization contract is ensured. No more &ldquo;half initialized objects&rdquo; anymore. And then we get this &#x1F937;&#x200D;&#x2640;&#xFE0F;<\/p><\/blockquote>\n\n<p>And it will crash any time the values aren&rsquo;t available, not just mid-initialization. It&rsquo;s strange because Core Data went to the trouble of adding <code>shouldDeleteInaccessibleFaults<\/code> so that exceptions (e.g. from objects that no longer exist) don&rsquo;t make Swift code crash. Instead, the Objective-C code will return default values for properties. But then actually accessing an absent value from Swift will crash as it tries to bridge an unexpected <code>nil<\/code> value. You can, however, <a href=\"https:\/\/mastodon.social\/@danluu\/110766175977114068\">check for<\/a> absent values by casting to an optional (even though the property is not optional).<\/p>\n\n<p><a href=\"https:\/\/useyourloaf.com\/blog\/swiftdata-saving-changes\/\">Keith Harrison<\/a>:<\/p>\n<blockquote cite=\"https:\/\/useyourloaf.com\/blog\/swiftdata-saving-changes\/\">\n<p>As with Core Data, SwiftData marks the object as changed if you call the setter on any of the properties of the object. That&rsquo;s the case even if you don&rsquo;t change the value of the property.<\/p>\n<\/blockquote>\n\n<p>Previously:<\/p>\n<ul>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2020\/01\/16\/optionals-in-swift-objective-c-interoperability\/\">Optionals in Swift Objective-C Interoperability<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2017\/08\/31\/using-lazy-variables-to-work-around-swift-initialization-rules\/\">Using Lazy Variables to Work Around Swift Initialization Rules<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2015\/12\/11\/double-core-data-accessors-by-omitting-nsmanaged\/\">Double Core Data Accessors by Omitting @NSManaged<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2015\/03\/17\/using-core-data-with-swift\/\">Using Core Data With Swift<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2014\/11\/25\/strange-tales-of-swift-initialization\/\">Strange Tales of Swift Initialization<\/a><\/li>\n<\/ul>\n\n<p id=\"swiftdata-update-2023-07-27\">Update (2023-07-27): <a href=\"https:\/\/mastodon.world\/@iandundas\/110778915717731326\">Ian<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.world\/@iandundas\/110778915717731326\"><p>Wow, watch out for this SwiftData bug in b5: Simply add a comment on the same line as a <code>Query<\/code> (!). The macro tries to pull it in as code and the result won&rsquo;t build[&#8230;]<\/p><\/blockquote>\n<p>That&rsquo;s a macro failure mode that I didn&rsquo;t expect.<\/p>\n<p>Previously:<\/p>\n<ul>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2023\/07\/17\/macros-in-swift-5-9\/\">Macros in Swift 5.9<\/a><\/li>\n<\/ul>\n\n<p id=\"swiftdata-update-2023-08-10\">Update (2023-08-10): <a href=\"https:\/\/chaos.social\/@donnywals\/110819225015961922\">Donny Wals<\/a>:<\/p>\n<blockquote cite=\"https:\/\/chaos.social\/@donnywals\/110819225015961922\"><p>The more I explore SwiftData by trying to implement the topics I cover in Practical Core Data the more I realize SwiftData is very much a beta framework.<\/p><p>I fully plan to write Practical SwiftData but right now I&rsquo;m wondering if iOS 17 is too soon for me to be able to write something that&rsquo;s more insightful than just the basics along with a bunch of &ldquo;this isn&rsquo;t supported right now&rdquo; notes&#8230;<\/p><\/blockquote>\n\n<p><a href=\"https:\/\/mastodon.social\/@helge\/110856488223701400\">Helge He&szlig;<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@helge\/110856488223701400\"><p>Since the release notes have been a little &ldquo;shallow&rdquo; for beta6, here is what I found for SwiftData so far:<\/p><ul><li><code>getValue(for:)<\/code> =&gt; <code>getValue(forKey:)<\/code><\/li><li><code>Entity<\/code> =&gt; <code>Schema.Entity<\/code>, etc<\/li><li><code>Property<\/code> =&gt; <code>SchemaProperty<\/code><\/li><li><code>deleteRule<\/code> =&gt; not an option anymore, own arg<\/li><li><code>objectID<\/code> =&gt; <code>persistentModelID<\/code><\/li><li><code>Entity.mangledName<\/code> gone<\/li><li><code>Property.isRelationship()<\/code> func is now a property<\/li><li><code>Attribute.nested<\/code> gone<\/li><li><code>superEntityName<\/code> =&gt; <code>superentityName<\/code> &#x1F648;<\/li><li><code>ctx.object(with:)<\/code> =&gt; <code>ctx.model(for:)<\/code><\/li><\/ul><\/blockquote>\n\n<p><a href=\"https:\/\/mastodon.social\/@Timschmitz\/110855791249334316\">Tim Schmitz<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@Timschmitz\/110855791249334316\"><p>I&rsquo;m starting to wonder if SwiftData is going to make it into iOS 17.0. The list of known issues is pretty long, and it&rsquo;s not the kind of thing you&rsquo;d want to ship half-baked. I hope they&rsquo;ll take the time to get it to a stable place rather than rush it out the door.<\/p><\/blockquote>\n\n<p id=\"swiftdata-update-2023-08-17\">Update (2023-08-17): <a href=\"https:\/\/mastodon.social\/@_inside\/110899214693196289\">Guilherme Rambo<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@_inside\/110899214693196289\"><p>Every new iOS 17 beta build causes SwiftData apps built with the previous Xcode 15 beta to crash on launch due to binary incompatibility. Apple released iOS 17 beta 6 yesterday, which did the same, but didn&rsquo;t release a new Xcode 15 beta &#x1F972; I&rsquo;m glad I haven&rsquo;t shipped any public TestFlight builds yet.<\/p><\/blockquote>\n\n<p><a href=\"https:\/\/mastodon.social\/@helge\/110901052759223851\">Helge He&szlig;<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@helge\/110901052759223851\"><p>SwiftData is still in heavy flux and changes in major ways every beta.<\/p><p>At release time they&rsquo;d have to pin down the ABI which makes me think it&rsquo;ll be dropped for the first iOS 17 release. (cutoff should be within weeks and it seems far from ready)<\/p><\/blockquote>\n\n<p id=\"swiftdata-update-2023-08-24\">Update (2023-08-24): <a href=\"https:\/\/mastodon.social\/@helge\/110935574814631036\">Helge He&szlig;<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@helge\/110935574814631036\">\n<p>My summary of SwiftData b7 changes[&#8230;]<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/mastodon.social\/@helge\/110938321039587884\">Helge He&szlig;<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@helge\/110938321039587884\"><p>Here is the expansion of the <code>Model<\/code> macro, it has some really funky stuff. I can&rsquo;t even compile the thing when manually expanding the macros? &#x1F914; Why would that be? Special compiler support?\nThis time around the regular properties seem to exist as real instance variables. An <code>_<\/code> peer is generated, w\/ <code>_SwiftDataNoType<\/code> &#x1F4A5;<\/p><\/blockquote>\n\n<p><a href=\"https:\/\/mastodon.social\/@helge\/110935473029392379\">Helge He&szlig;<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@helge\/110935473029392379\"><p>In Beta7 SwiftData allows initialization as part of the property declaration again. But since they are moved to a different place by the macro, they can&rsquo;t use type inference. They do seem to set both the model object ivar value and the default in the storage (which I think makes sense).<\/p><\/blockquote>\n\n<p id=\"swiftdata-update-2023-09-06\">Update (2023-09-06): <a href=\"https:\/\/mastodon.social\/@helge\/111012552714767956\">Helge He&szlig;<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@helge\/111012552714767956\"><p>Interesting, the SwiftData Model macro doesn&rsquo;t have an <code>originalName<\/code>. Isn&rsquo;t that necessary for table renaming\/migration?<\/p><\/blockquote>\n\n<p><a href=\"https:\/\/mastodon.social\/@helge\/111017900878802176\">Helge He&szlig;<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@helge\/111017900878802176\"><p>I think there is a different wrt transient properties between SwiftData and CoreData. The latter still tracks transient attributes, it just doesn&rsquo;t persist them.<\/p><p>SwiftData doesn&rsquo;t seem to include them into the schema at all (neither in the KVC metadata). Also: They do not register w\/ Observation, I wonder whether that is a bug. I.e. a change to a transient property may not trigger a SwiftUI view refresh.<\/p><\/blockquote>\n\n<p id=\"swiftdata-update-2023-09-14\">Update (2023-09-14): <a href=\"https:\/\/mastodon.social\/@helge\/111054337568375984\">Helge He&szlig;<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@helge\/111054337568375984\">\n<p>As far as I can tell there are no major changes to the SwiftData API in Xcode 15 RC. The RC generally seems to be a major improvement, also in swiftc, it successfully compiles a test app again. Most of my tests run, if I disable a lot.\nI still have the impression that it gets confused w\/ types. I suspect it is related to having the same non-qualified type names (e.g. <code>@model class CountTests.Item<\/code> and also a <code>@model class FetchTests.Item<\/code>, different in structure).<\/p>\n<\/blockquote>","protected":false},"excerpt":{"rendered":"<p>Apple (Hacker News): Combining Core Data&rsquo;s proven persistence technology and Swift&rsquo;s modern concurrency features, SwiftData enables you to add persistence to your app quickly, with minimal code and no external dependencies. Using modern language features like macros, SwiftData enables you to write code that is fast, efficient, and safe, enabling you to describe the entire [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"2023-06-12T18:18:26Z","apple_news_api_id":"5a195c9b-22e2-404d-82e6-503af7e5ee4a","apple_news_api_modified_at":"2023-09-14T12:22:09Z","apple_news_api_revision":"AAAAAAAAAAAAAAAAAAAAGA==","apple_news_api_share_url":"https:\/\/apple.news\/AWhlcmyLiQE2C5lA69-XuSg","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[109,31,2321,30,2385,941,71,1774,2200,901,2404],"class_list":["post-39698","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-coredata","tag-ios","tag-ios-17","tag-mac","tag-macos-14-sonoma","tag-macros","tag-programming","tag-swift-codable","tag-swift-concurrency","tag-swift-programming-language","tag-swiftdata"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/39698","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=39698"}],"version-history":[{"count":28,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/39698\/revisions"}],"predecessor-version":[{"id":40645,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/39698\/revisions\/40645"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=39698"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=39698"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=39698"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}