Swift
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Optionals
-
Section 4: Object-Oriented and Value Types
-
Section 5: Memory Management
-
Section 6: Generics and Error Handling
-
Section 7: Concurrency
-
Section 8: Working with Collections
-
Section 9: Codable and Data Handling
-
Section 10: Protocol-Oriented Programming
-
Section 11: Testing and Tooling
-
Section 12: Practical Projects
-
Section 13: Interview Practice
-
Section 14: More Practice Exercises
-
Section 15: More Standard Library
-
Section 16: Advanced Concurrency
-
Section 17: Foundation Framework Deep Dive
-
Section 18: URLSession and Networking Deep Dive
-
Section 19: Combine Framework
-
Section 20: SwiftUI Fundamentals for Swift Developers
-
Section 21: Server-Side Swift with Vapor
-
Section 22: Swift Package Manager Deep Dive
-
Section 23: Swift Concurrency Deep Dive
-
Section 24: More Language Features
-
Section 25: Error Handling Deep Dive
-
Section 26: Testing Deep Dive
-
Section 27: Data Structures and Algorithms in Swift
-
Section 28: More Practice Exercises
-
Section 29: More Interview Practice
-
Section 30: Swift Macros (Swift 5.9+)
-
Section 31: Property Wrappers Ecosystem
-
Section 32: Swift Interop Deep Dive
-
Section 33: iOS App Architecture Patterns
-
Section 34: Performance and Debugging
-
Section 35: App Distribution and CI/CD
-
Section 36: More Practical Projects
-
Section 37: SwiftData and Persistence
-
Section 38: More Design Patterns
-
Section 39: More Review and Practice
-
Section 40: More Foundation Deep Dive
-
Section 41: Advanced Collections in Swift
-
Section 42: Advanced Generics Practice
-
Section 43: UIKit for Legacy and Hybrid Apps
-
Section 44: watchOS and visionOS Development Basics
-
Section 45: More Networking Patterns
-
Section 46: More Testing Practice
-
Section 47: Accessibility in Swift Apps
-
Section 48: Localization
-
Section 49: More Practical Projects Round 2
-
Section 50: Swift Charts Framework
-
Section 51: More Interview and Algorithm Practice
-
Section 52: Final Practice and Mastery
-
Section 53: Swift Compiler and Build System
-
Section 54: More Concurrency Practice
-
Section 55: App Store Guidelines and Review
-
Section 56: More Design and Architecture
162: Migrating from Core Data to SwiftData
If you've been following the Apple developer blogs, you might have fallen for the most common trap in the SwiftData transition: the belief that SwiftData is a brand-new database engine that replaces Core Data entirely. I've seen plenty of developers start panicking, thinking they need to write a complex migration script to export their existing SQLite data into a "new" format just to use the @Model macro.
That is completely wrong. SwiftData isn't a replacement for the underlying persistence engine; it's a modern, Swift-native layer built on top of the Core Data stack. In fact, it uses the same SQLite store. If you have an existing Core Data store and you define your SwiftData models to match your old .xcdatamodeld entities, SwiftData can often open that existing file without you moving a single row of data manually.
"SwiftData is a different database" vs. "SwiftData is a modern wrapper"
Think of it this way: Core Data is like a massive, industrial-grade power plant with a thousand levers and dials. SwiftData is like a sleek, modern light switch installed on your wall. The power coming into your house is exactly the same; the interface for controlling it is just significantly less painful.
Let's say you have a "Personal Library" app. In Core Data, you had an entity called Book with attributes title (String) and pageCount (Integer 64). To migrate, you don't need to "import" that data. You just define a SwiftData model that mirrors it:
@Model
class Book {
var title: String
var pageCount: Int
init(title: String, pageCount: Int) {
self.title = title
self.pageCount = pageCount
}
}
As long as the class name and the property names match the entity and attribute names in your old .xcdatamodeld file, SwiftData recognizes the schema. I've found that as long as you don't change the underlying types (like changing an Int to a String), the transition is nearly invisible to the user.
"Manual SQLite migration is required" vs. "Matching the Schema"
The real "magic" happens when you initialize your ModelContainer. You don't need to point it to a new file; you point it to the same store URL your Core Data stack was using. SwiftData looks at the existing SQLite file, compares it to your @Model classes, and says, "Yeah, this looks like the same data," and just starts working.
However, there is a catch. If you had complex custom migrations or highly specific Core Data configurations (like custom atomic store types), you can't just flip a switch. But for 90% of us using standard SQLite stores, the migration is a matter of alignment. You need to ensure your @Model definitions are an exact mirror of your Core Data entity definitions. If you renamed pageCount to totalPages in your new Swift code, SwiftData will think it's a new property and you'll lose the data in that column unless you provide a SchemaMigrationPlan.
"ModelContainers are for fresh starts" vs. "Connecting to legacy stores"
When you set up your ModelContainer in the App struct, you're essentially telling the app where the data lives. I usually recommend explicitly defining the configuration if you're migrating, just to be certain you're hitting the right file.
let config = ModelConfiguration(url: existingCoreDataStoreURL)
let container = try ModelContainer(for: Book.self, configurations: config)
Once this is connected, you can stop using NSManagedObjectContext and start using @Query in your SwiftUI views. The data is still there, sitting in the same SQLite file, but you're finally free from the boilerplate of fetching requests and managed object contexts. It's a massive relief, honestly.
📋 Practical Task
Migrating the Vintage Vinyl Collection Schema
You are taking over a legacy app that tracks a vinyl record collection. The existing Core Data store has an entity called Record with the following attributes: albumName (String), artist (String), and releaseYear (Integer 16).
Your task is to implement the SwiftData migration. Create a Swift file that defines the Record model using the @Model macro. Ensure the property names and types exactly match the legacy Core Data schema to allow for a seamless migration without data loss. Then, write a small snippet of code that would initialize a ModelContainer for this Record model using a specific URL provided as legacyStoreURL.
There are no comments for now.