Core Data Stack
What is Core Data?
Core Data is Apple's object graph and persistence framework. It manages object lifecycles, relationships, and serialization to SQLite.
NSPersistentContainer
The container manages the entire Core Data stack:
import CoreData
let container = NSPersistentContainer(name: "MyApp")
container.loadPersistentStores { description, error in
if let error = error {
fatalError("Core Data failed to load: \(error.localizedDescription)")
}
}
let context = container.viewContext
Stack Components
- NSManagedObjectContext: In-memory scratchpad for objects
- NSPersistentStoreCoordinator: Manages persistent stores
- NSManagedObjectModel: Defines your data model
Background Context
For heavy operations off the main thread:
let backgroundContext = container.newBackgroundContext()
backgroundContext.perform {
let obj = NSEntityDescription.insertNewObject(forEntityName: "Article", into: backgroundContext)
try? backgroundContext.save()
}
SwiftUI Integration
@main
struct MyApp: App {
let container: NSPersistentContainer
init() {
container = NSPersistentContainer(name: "MyApp")
container.loadPersistentStores { _, error in
if let error = error { fatalError("Failed: \(error)") }
}
}
var body: some Scene {
WindowGroup { ContentView() }
.environment(\.managedObjectContext, container.viewContext)
}
}
Managed Objects
NSManagedObject Subclasses
Generate or create typed subclasses:
@objc(Article)
public class Article: NSManagedObject {
@NSManaged public var id: UUID
@NSManaged public var title: String
@NSManaged public var content: String
@NSManaged public var publishedAt: Date
@NSManaged public var author: Author?
}
extension Article {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Article> {
return NSFetchRequest<Article>(entityName: "Article")
}
}
Creating and Saving
let article = Article(context: context)
article.id = UUID()
article.title = "Hello World"
article.publishedAt = Date()
try? context.save()
Relationships
@objc(Author)
public class Author: NSManagedObject {
@NSManaged public var name: String
@NSManaged public var articles: NSSet?
}
// Access
if let articles = author.articles?.allObjects as? [Article] {
for article in articles { print(article.title) }
}
// Set
author.addToArticles(article)
Fetch Requests
Basic Fetch
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Article")
let articles = try context.fetch(request) as? [Article] ?? []
Predicates
request.predicate = NSPredicate(format: "isPublished == %@", NSNumber(value: true))
request.predicate = NSPredicate(format: "title CONTAINS[cd] %@", searchText)
request.predicate = NSPredicate(format: "publishedAt > %@", lastWeek as NSDate)
let compound = NSCompoundPredicate(andPredicateWithSubpredicates: [
NSPredicate(format: "isPublished == %@", true),
NSPredicate(format: "title CONTAINS %@", searchText)
])
request.predicate = compound
Sorting and Limits
request.sortDescriptors = [
NSSortDescriptor(key: "publishedAt", ascending: false),
NSSortDescriptor(key: "title", ascending: true)
]
request.fetchLimit = 20
request.fetchOffset = 0
request.fetchBatchSize = 20
Batch Operations
Delete multiple objects efficiently:
let batchDelete = NSBatchDeleteRequest(fetchRequest: Article.fetchRequest())
try? context.execute(batchDelete)
// Batch update
let batchUpdate = NSBatchUpdateRequest(entityName: "Article")
batchUpdate.predicate = NSPredicate(format: "isPublished == %@", false)
batchUpdate.propertiesToUpdate = ["isPublished": true]
try? context.execute(batchUpdate)
Async Fetch
let fetchRequest = Article.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "isPublished == %@", true)
let articles = try await context.perform {
try self.context.fetch(fetchRequest)
}
Quiz
1. What is NSPersistentContainer?
2. What property wrapper defines Core Data attributes?
3. What is NSBatchDeleteRequest used for?
4. How do you perform Core Data operations off the main thread?
Flashcards
Question
What is the Core Data stack?
Click to reveal answer
Answer
Three components: NSManagedObjectContext (scratchpad), NSPersistentStoreCoordinator (store manager), NSManagedObjectModel (schema).
Question
How do you create a background context?
Click to reveal answer
Answer
Use container.newBackgroundContext() and perform operations within perform {} block.
Question
What is NSFetchRequest?
Click to reveal answer
Answer
A request object used to fetch data from Core Data with predicates, sort descriptors, and limits.
Question
How do you batch delete in Core Data?
Click to reveal answer
Answer
Use NSBatchDeleteRequest with a fetch request to delete objects at the store level.
Revision Notes
Key Takeaways
- 1. NSPersistentContainer manages the entire Core Data stack
- 2. @NSManaged marks Core Data-managed properties
- 3. Use background contexts for heavy operations to avoid blocking the UI
- 4. NSBatchDeleteRequest and NSBatchUpdateRequest handle bulk operations efficiently
- 5. NSFetchRequest with predicates provides flexible data querying
Interview Tips
- • Explain the Core Data stack components and their roles
- • Know the difference between viewContext and background contexts
- • Describe when to use batch operations vs individual deletes
- • Discuss Core Data vs SwiftData trade-offs
Cheat Sheet
NSPersistentContainer: Encapsulates Core Data stack. NSManagedObjectContext: Object scratchpad. @NSManaged: Core Data properties. NSFetchRequest with predicates and sort descriptors. NSBatchDeleteRequest for bulk deletes. Background contexts for off-main-thread work.