Core Data là framework của Apple để quản lý đồ thị đối tượng trong các ứng dụng iOS và macOS. Nó cung cấp khả năng lưu trữ dữ liệu, theo dõi thay đổi, hoàn tác thao tác và tích hợp UI thông qua NSFetchedResultsController. Theo tài liệu Apple Developer (2025), Core Data không phải là cơ sở dữ liệu — nó là lớp mô hình hóa đối tượng mặc định sử dụng SQLite làm bộ lưu trữ bền vững để tải và lưu đối tượng.
Những điểm chính
Core Data là framework quản lý đồ thị đối tượng và lưu trữ bền vững thuộc SDK Cocoa Touch của Apple. Nó cung cấp giao diện hướng đối tượng để làm việc với dữ liệu: nhà phát triển thao tác với các thực thể, thuộc tính và mối quan hệ, trong khi Core Data chuyển đổi các đối tượng này thành bản ghi cơ sở dữ liệu quan hệ bên dưới.
Core Data được giới thiệu trong Mac OS X 10.4 Tiger (2005) cho macOS và được chuyển sang iOS 3.0 (2009). Trong hơn 20 năm, framework đã phát triển từ một lớp trừu tượng đơn giản trên SQLite thành một ngăn xếp đầy đủ tính năng với hỗ trợ đồng bộ hóa đám mây qua NSPersistentCloudKitContainer, đa luồng qua quản lý ngữ cảnh tự động và tải bất đồng bộ qua Swift Concurrency.
Theo khảo sát nhà phát triển iOS của Slack Community (2025), Core Data được sử dụng trong 68% ứng dụng iOS thương mại để lưu trữ dữ liệu cục bộ. Bất chấp chỉ trích về độ phức tạp và kiến trúc nhiều lớp, framework vẫn là tiêu chuẩn cho ứng dụng Apple nhờ tích hợp chặt chẽ với hệ thống, chi phí bằng không (tích hợp trong SDK) và hỗ trợ đồng bộ iCloud.
Một quan niệm sai phổ biến là coi Core Data như cơ sở dữ liệu. Framework không thực thi truy vấn SQL trực tiếp và không phải là DBMS. Core Data là lớp quản lý đồ thị đối tượng có thể sử dụng bộ lưu trữ SQLite, Binary hoặc In-Memory để lưu trữ bền vững. Tương tự: Core Data giống như Hibernate hoặc Entity Framework nhưng cho hệ sinh thái Apple, và SQLite bên dưới giống như MySQL bên dưới Hibernate.
Ngăn xếp Core Data gồm bốn thành phần kết nối với nhau: NSManagedObjectModel (lược đồ dữ liệu), NSPersistentStoreCoordinator (điều phối viên lưu trữ), NSManagedObjectContext (ngữ cảnh làm việc) và NSPersistentContainer (vùng chứa thống nhất kết hợp cả ba từ iOS 10). NSPersistentContainer tự động hóa việc tạo và cấu hình ngăn xếp.
Mỗi thành phần thực hiện chức năng được xác định chặt chẽ. NSManagedObjectModel tải tệp .xcdatamodeld với mô tả thực thể. NSPersistentStoreCoordinator kết nối mô hình với tệp lưu trữ vật lý (SQLite). NSManagedObjectContext cung cấp vùng tạm thời để làm việc với đối tượng. Vùng chứa hợp nhất mọi thứ trong một lời gọi khởi tạo duy nhất.
SQLite (NSSQLiteStoreType) là bộ lưu trữ tiêu chuẩn được sử dụng trong hầu hết ứng dụng. Dữ liệu được lưu vào một tệp .sqlite duy nhất với hỗ trợ giao dịch ACID. Binary (NSBinaryStoreType) là bộ lưu trữ định dạng nhị phân cho tập dữ liệu nhỏ (tới vài trăm đối tượng). In-Memory (NSInMemoryStoreType) là bộ lưu trữ tạm thời trong RAM không lưu vào đĩa, dùng cho kiểm thử và bộ đệm.
| Loại lưu trữ | Định dạng | Hiệu suất | Khi nào sử dụng |
|---|---|---|---|
| SQLite | .sqlite | Cao | Lựa chọn tiêu chuẩn cho sản xuất |
| Binary | .binary | Trung bình | Tập dữ liệu nhỏ |
| In-Memory | RAM | Tối đa | Kiểm thử, bộ đệm, dữ liệu tạm |
| CloudKit | iCloud | Phụ thuộc mạng | Đồng bộ giữa các thiết bị |
Loại bộ lưu trữ được đặt bằng một dòng khi khởi tạo NSPersistentStoreDescription. Nhà phát triển có thể chuyển từ SQLite sang In-Memory cho kiểm thử đơn vị hoặc sang CloudKit cho đồng bộ iCloud mà không cần thay đổi mã thao tác đối tượng — Core Data trừu tượng hóa sự khác biệt giữa các loại lưu trữ thông qua API ngữ cảnh thống nhất.
NSManagedObject là lớp cơ sở cho tất cả đối tượng Core Data, đại diện cho một bản ghi thực thể duy nhất. Mỗi đối tượng được quản lý có một NSManagedObjectID duy nhất (định danh bền vững), được gắn với một ngữ cảnh và theo dõi các thay đổi qua KVO (Key-Value Observing). Nhà phát triển tạo lớp con của NSManagedObject để định nghĩa thuộc tính thực thể có kiểu.
NSManagedObjectContext là thành phần trung tâm của Core Data cung cấp không gian làm việc cho tất cả thao tác với đối tượng. Ngữ cảnh theo dõi thêm, xóa và thay đổi (theo dõi thay đổi), hỗ trợ hoàn tác thao tác qua undoManager và tự động hợp nhất thay đổi từ ngữ cảnh khác khi nhận thông báo lưu.
Quy tắc hàng đợi riêng: NSManagedObjectContext được tạo với .privateQueueConcurrencyType hoặc .mainQueueConcurrencyType. Ngữ cảnh chính gắn với luồng UI chính, trong khi ngữ cảnh riêng chạy trên hàng đợi nền. Mỗi ngữ cảnh chỉ được sử dụng trên hàng đợi của chính nó — truy cập đối tượng được quản lý từ luồng khác gây ra sập ứng dụng. parentContext cho phép tổ chức hệ thống phân cấp ngữ cảnh cho ghi bất đồng bộ.
struct CoreDataStack {
let container: NSPersistentContainer
init(name: String) {
container = NSPersistentContainer(name: name)
container.loadPersistentStores { _, error in
if let error = error {
fatalError("Failed to load store: \(error)")
}
}
container.viewContext.automaticallyMergesChangesFromParent = true
}
func backgroundContext() -> NSManagedObjectContext {
let context = container.newBackgroundContext()
context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
return context
}
}
NSPersistentContainer tự động tạo viewContext (hàng đợi chính) và cung cấp newBackgroundContext() cho thao tác nền. Đặt automaticallyMergesChangesFromParent = true làm cho viewContext tự động nhận thay đổi từ ngữ cảnh nền khi chúng lưu, cập nhật UI mà không cần truy vấn lại dữ liệu thủ công.
NSPersistentStoreCoordinator quản lý bộ lưu trữ dữ liệu vật lý: mở tệp, tạo bảng SQLite dựa trên mô hình và thực hiện di trú khi lược đồ thay đổi. Khi khởi tạo NSPersistentStoreDescription với NSSQLiteStoreType, Core Data tạo tệp SQLite với lược đồ tương ứng với mô hình .xcdatamodeld.
Core Data không sử dụng truy vấn SQL tiêu chuẩn qua SELECT/INSERT/UPDATE. Thay vào đó, nó tạo lệnh SQL nội bộ dựa trên mô hình và truy vấn thực hiện qua NSFetchRequest. Nhà phát triển có thể bật ghi nhật ký SQL bằng đối số khởi chạy -com.apple.CoreData.SQLDebug 1 để gỡ lỗi hiệu suất truy vấn.
Di trú nhẹ (Lightweight Migration) là quá trình tự động cập nhật lược đồ SQLite khi thêm thuộc tính mới, thay đổi cờ optional/required hoặc đổi tên bằng renamingID. Di trú nặng yêu cầu cho thay đổi lược đồ căn bản như hợp nhất hoặc tách thực thể và được thực hiện qua NSMigrationManager tùy chỉnh.
let description = NSPersistentStoreDescription()
description.url = FileManager.default
.urls(for: .documentDirectory, in: .userDomainMask)
.first?
.appendingPathComponent("Model.sqlite")
description.setOption(true as NSNumber,
forKey: NSMigratePersistentStoresAutomaticallyOption)
description.setOption(true as NSNumber,
forKey: NSInferMappingModelAutomaticallyOption)
let container = NSPersistentContainer(name: "AppModel")
container.persistentStoreDescriptions = [description]
container.loadPersistentStores { _, error in
if let error = error { print("Migration error: \(error)") }
}
Thiết lập di trú tự động qua NSMigratePersistentStoresAutomaticallyOption và NSInferMappingModelAutomaticallyOption cho phép Core Data tự động cập nhật tệp SQLite khi thêm thuộc tính hoặc thực thể trong phiên bản mới của mô hình. Nếu không thể di trú, điều phối viên lưu trữ ném lỗi kèm mô tả lý do — nhà phát triển phải triển khai di trú tùy chỉnh qua NSMigrationManager.
NSFetchRequest là công cụ chính để lấy đối tượng từ Core Data. Một yêu cầu chứa tên thực thể, vị từ (bộ lọc), bộ mô tả sắp xếp, giới hạn và độ lệch. Kết quả trả về dưới dạng mảng NSManagedObject hoặc lớp con có kiểu. NSPredicate hỗ trợ điều kiện phức tạp với AND, OR, IN, LIKE và truy vấn con.
NSBatchDeleteRequest là cách hiệu quả để xóa hàng loạt đối tượng mà không tải từng đối tượng vào bộ nhớ. Yêu cầu thực thi ở cấp SQLite, bỏ qua ngữ cảnh đối tượng được quản lý và chỉ cập nhật ngữ cảnh sau khi hoàn thành. Yêu cầu hàng loạt tương tự tồn tại cho cập nhật (NSBatchUpdateRequest) và chèn (NSBatchInsertRequest).
CRUD (Create, Read, Update, Delete) trong Core Data được thực hiện qua phương thức ngữ cảnh: insert, fetch, save và delete. Tất cả thay đổi là tạm thời cho đến khi gọi context.save() — phương thức này lưu thay đổi vào bộ lưu trữ SQLite bền vững. Khi lỗi lưu, ngữ cảnh giữ nguyên trạng thái đã thay đổi để thử lại.
let context = container.viewContext
// Tạo
let user = User(context: context)
user.id = 42
user.name = "Alice"
// Đọc
let request = User.fetchRequest()
request.predicate = NSPredicate(format: "name CONTAINS %@", "Ali")
request.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)]
let results = try context.fetch(request)
// Cập nhật
results.first?.name = "Alice Updated"
// Xóa
if let first = results.first { context.delete(first) }
// Lưu
try context.save()
Lưu ngữ cảnh (context.save()) là thao tác quan trọng. Nếu không gọi save, tất cả thay đổi chỉ ở trong bộ nhớ. Ngữ cảnh theo dõi trạng thái hasChanges, có thể kiểm tra trước khi lưu. Cho thao tác nền, sử dụng newBackgroundContext với lưu riêng, và cho UI, sử dụng viewContext với tự động lưu theo bộ đếm thời gian hoặc khi ứng dụng vào nền.
Thực hành thứ nhất — sử dụng NSPersistentCloudKitContainer để đồng bộ dữ liệu giữa các thiết bị người dùng qua iCloud. Đồng bộ đám mây được kích hoạt bằng cách thêm tùy chọn CloudKit vào mô tả bộ lưu trữ bền vững. Core Data tự động quản lý xung đột đồng bộ và hợp nhất thay đổi từ thiết bị khác.
Thực hành thứ hai — tránh fetchRequest không có vị từ trên bảng lớn. Mỗi lần tải vô điều kiện tải tất cả đối tượng thực thể vào bộ nhớ, gây tiêu thụ RAM cao và làm chậm UI. Luôn sử dụng vị từ và giới hạn. Cho phân trang, sử dụng fetchLimit và fetchOffset trong NSFetchRequest.
Thực hành thứ ba — cấu hình mergePolicy để giải quyết xung đột khi truy cập đa luồng. NSMergeByPropertyObjectTrumpMergePolicy cập nhật thuộc tính xung đột từ ngữ cảnh đã lưu cuối cùng. NSRollbackMergePolicy hủy thay đổi ngữ cảnh hiện tại khi xung đột. Lựa chọn chính sách phụ thuộc vào logic nghiệp vụ của ứng dụng.
Thực hành thứ tư — sử dụng NSFetchedResultsController để tích hợp với bảng và bộ sưu tập. Nó tự động đăng ký thông báo NSManagedObjectContextDidSave, chỉ tải đối tượng cần thiết (faulting) và thông báo cho ủy quyền về chèn, xóa và di chuyển với đường dẫn chỉ mục thích hợp cho hoạt ảnh UITableView.
Faulting là cơ chế tải lười của Core Data. Đối tượng được quản lý trả về bởi yêu cầu tải ở trạng thái fault — các thuộc tính của nó chưa được tải đầy đủ, chỉ có định danh. Tải đầy đủ (fire fault) xảy ra khi truy cập đầu tiên vào bất kỳ thuộc tính nào. Relationship prefetching (setRelationshipKeyPathsForPrefetching) tải đối tượng liên quan trước, tránh truy vấn N+1.
extension UserRepository {
func fetchUsersWithPosts() throws -> [User] {
let request = User.fetchRequest()
request.predicate = NSPredicate(format: "isActive == YES")
request.relationshipKeyPathsForPrefetching = ["posts"]
request.returnsObjectsAsFaults = false
request.fetchBatchSize = 20
let context = container.viewContext
return try context.fetch(request)
}
}
fetchBatchSize = 20 buộc Core Data tải dữ liệu theo lô 20 đối tượng (để hiển thị màn hình), mà không tải toàn bộ bảng cùng lúc. Cờ returnsObjectsAsFaults = false đảm bảo tất cả thuộc tính người dùng được tải ngay lập tức, hữu ích cho hiển thị trực tiếp. Prefetching mối quan hệ “posts” tránh truy vấn riêng cho mỗi người dùng khi truy cập bài viết.
Câu hỏi thường gặp
Không, Core Data là framework quản lý đồ thị đối tượng. Nó cung cấp API để làm việc với đối tượng, theo dõi thay đổi và lưu trữ chúng. Cơ sở dữ liệu bên dưới Core Data (mặc định là SQLite) không nên nhầm lẫn với chính framework. Core Data là ORM, không phải DBMS.
Có, Core Data hỗ trợ ba loại lưu trữ: SQLite, Binary và In-Memory. Loại lưu trữ được đặt qua NSPersistentStoreDescription. Bộ lưu trữ In-Memory không lưu dữ liệu vào đĩa và phù hợp cho kiểm thử đơn vị. Bộ lưu trữ Binary là định dạng kế thừa cho tập đối tượng nhỏ gọn.
Cho di trú nhẹ, bật NSMigratePersistentStoresAutomaticallyOption và NSInferMappingModelAutomaticallyOption. Cho thay đổi phức tạp, tạo Mapping Model (.xcmappingmodel) qua Xcode. Bộ lưu trữ CloudKit (NSPersistentCloudKitContainer) hỗ trợ di trú tự động khi đồng bộ lược đồ với máy chủ iCloud.
SwiftData là framework Apple mới (iOS 17+) được xây dựng trên Core Data sử dụng Swift Macros và Swift Concurrency. SwiftData có cú pháp đơn giản hơn: thực thể được mô tả bằng macro @Model, ngữ cảnh bằng @Environment(\.modelContext). Bên dưới, SwiftData sử dụng cùng ngăn xếp Core Data và SQLite.
Bật đối số khởi chạy -com.apple.CoreData.SQLDebug 1 — Core Data sẽ xuất tất cả truy vấn SQL và thời gian thực thi ra bảng điều khiển Xcode. Để phân tích hiệu suất, sử dụng Instruments với mẫu Core Data, hiển thị số lượng yêu cầu fault, thời gian tải đối tượng và thời gian lưu ngữ cảnh.
Tổng kết
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm