Skip to content

← All tools

Free tool · runs in your browser

Core Data model to SwiftData converter

Paste the contents file from inside your .xcdatamodel and get one SwiftData @Model class per entity, with Swift types, optionals and default values, @Attribute options for unique constraints, external storage and renaming identifiers, @Transient for transient attributes, and @Relationship with the delete rule and inverse, plus an init. A notes list says what did not convert cleanly, such as fetched properties, derived attributes, ordered relationships and CloudKit limits. The file is read in this page and never uploaded.

Your Core Data model

Paste the contents file from inside your .xcdatamodel (it is XML), or drop it here. Nothing is uploaded.

Drop the contents file here

Paste or drop a model to see the SwiftData classes.

Where the facts come from

How the conversion works

  • •Types: Integer 16, 32 and 64 become Int16, Int32 and Int64; Double, Float, Decimal and String keep their names; Boolean becomes Bool; Binary becomes Data; URI becomes URL; Date and UUID stay as they are. A Transformable attribute keeps its class name from the model, with .transformable(by:) when the model names a transformer.
  • •Optional and defaults: an optional attribute becomes an optional property. A default value in the model becomes the default in the Swift declaration and in the init. A required attribute with no default becomes a required init parameter.
  • •Attribute options: a single-attribute uniqueness constraint becomes @Attribute(.unique); a constraint over several attributes becomes the #Unique macro, which Apple lists for iOS 18 and macOS 15 and later. Allows External Storage becomes .externalStorage, and a renaming identifier becomes originalName:. A transient attribute becomes @Transient and stays out of the init.
  • •Relationships: to-many becomes an array, and the delete rules Nullify, Cascade, Deny and No Action become .nullify, .cascade, .deny and .noAction. The inverse: key path is written on one side of each pair only, the to-many side when there is one, which is how Apple's examples write it.
  • •Inheritance: a child entity becomes a subclass with an @available(iOS 26, ...) line, and its parent is left non-final, as in Apple's article Adopting inheritance in SwiftData. Its init calls super.init.
  • •Fetch indexes made of binary elements become the #Index macro (iOS 18 and macOS 15 and later). Everything else that has no counterpart is listed in the notes instead of being guessed.

What it does not do

  • •It does not move the data in an existing store, and it does not write a migration plan. Apple's names for that work are VersionedSchema and SchemaMigrationPlan; read the Apple pages on them before you change the model of an app that is already shipped.
  • •It does not convert fetched properties, derived attributes or composite attributes; it lists them. Entity configurations are not carried over either.
  • •It does not know your custom classes. A Transformable type is written as the class name the model gives, and you still import the framework that defines it.
  • •It does not check that the result builds in your project. Read the code, add it to your target and build. If your model is meant to sync with CloudKit, check the result with the SwiftData and CloudKit checker.
  • •It does not upload or save anything. Close the tab and the model is gone.

Questions

Where do I find the XML to paste?
In Finder, right-click the .xcdatamodeld folder, choose Show Package Contents, open the .xcdatamodel folder inside it, and open the file named contents. It is plain XML. The page also reads a dropped file. An app with several model versions has one .xcdatamodel per version; use the one you want to convert.
Does SwiftData support entity inheritance like Core Data?
Yes. Apple's article Adopting inheritance in SwiftData shows model subclasses written with @Model, and its examples mark the subclasses @available(iOS 26, *). Apple also says to avoid inheritance when a Boolean or an enumeration could tell the cases apart, and when your queries never need the base class. This page converts parent and child entities that way and notes every one of them.
How do the delete rules map?
Apple lists four Schema.Relationship.DeleteRule cases: cascade deletes any related models, deny prevents the deletion of a model that still has related models, noAction makes no changes to related models, and nullify clears the related model's reference to the deleted model. They match Core Data's Cascade, Deny, No Action and Nullify one for one.
Why is the inverse written on only one side?
Apple's SwiftData examples put inverse: on one side of a relationship pair and let SwiftData set the other. This page writes it on the to-many side of each pair, or on one chosen side when both are to-one, and keeps the delete rule of the other side as its own @Relationship line when it is not Nullify.
What breaks if the model syncs with CloudKit?
Apple's SwiftData page on syncing says CloudKit cannot enforce the unique option, requires relationships to be optional, and does not support the deny delete rule. Apple's Core Data page on CloudKit models adds that unique constraints are not supported and every relationship needs an inverse. If the model is marked as used with CloudKit, the notes list each property that runs into those rules.
Will my existing store open with the new classes?
This page cannot tell you. It writes classes with the same entity names, property names and types; Apple's sample for adopting SwiftData in a Core Data app keeps identical entity names, properties and relationships between the two versions. Whether an existing store opens, and how to change a model that has shipped, is covered by Apple's pages on VersionedSchema and SchemaMigrationPlan; test with a copy of real data.

Guides that use this tool

Related