Core Data — khái niệm, mô hình dữ liệu và cách hoạt động

Tác giả: IT Sectr Đã đăng: 2026-05-04 Thời gian đọc: 8 phút

Core Data là một framework quản lý dữ liệu của Apple cung cấp ánh xạ đối tượng-quan hệ cho iOS, macOS, tvOS và watchOS. Nó tự động hóa việc lưu, truy xuất và lọc các đối tượng trong ứng dụng, hoạt động trên SQLite, XML hoặc bộ nhớ nhị phân. Theo Apple Core Data Documentation, framework sử dụng các khái niệm Managed Object Context và NSPersistentContainer để quản lý ngăn xếp lưu trữ bền vững.

Những điểm chính

  • Core Data — framework của Apple để quản lý dữ liệu đối tượng-quan hệ trong ứng dụng.
  • NSManagedObjectModel — mô tả lược đồ dữ liệu: Entity, Attributes và Relationships.
  • NSManagedObject — đối tượng tương ứng với một bản ghi trong kho lưu trữ Core Data.
  • NSManagedObjectContext — không gian làm việc để tạo, đọc và lưu đối tượng.
  • NSPersistentContainer — ngăn xếp thống nhất kết hợp mô hình, context và bộ điều phối lưu trữ.

Core Data là gì và vai trò của nó trong iOS

Core Data là một framework quản lý đồ thị đối tượng và lưu trữ bền vững, là một phần của Cocoa Touch. Trái ngược với quan niệm sai lầm phổ biến, Core Data không phải là cơ sở dữ liệu, mà là một lớp quản lý đối tượng có thể sử dụng SQLite như một trong các kho lưu trữ. Nhiệm vụ chính của Core Data là theo dõi các thay đổi của đối tượng, quản lý vòng đời của chúng và đồng bộ hóa trạng thái với đĩa.

Framework cung cấp một đồ thị đối tượng nơi mỗi Managed Object được context theo dõi các thay đổi. Khi lưu, tất cả các đối tượng đã sửa đổi, thêm và xóa được cam kết vào kho lưu trữ bền vững trong một giao dịch duy nhất. Điều này loại bỏ nhu cầu nhà phát triển phải viết truy vấn SQL và quản lý giao dịch thủ công.

Theo thống kê của Swift Developer Survey (2025), Core Data được sử dụng trong 52% ứng dụng iOS làm việc với dữ liệu cục bộ. Mặc dù có sự xuất hiện của các giải pháp thay thế hiện đại (SwiftData, Realm), Core Data vẫn là framework chính trong các dự án Apple hiện có nhờ sự trưởng thành và tích hợp sâu với hệ thống.

Sử dụng Core Data cho các dự án có mô hình dữ liệu độ phức tạp trung bình, nơi cần có mối quan hệ giữa các đối tượng, hoàn tác thay đổi và bộ nhớ đệm tự động thông qua cơ chế faulting.

Kiến trúc Core Data được xây dựng xoay quanh khái niệm Managed Object Context — một không gian làm việc theo dõi tất cả các thay đổi của đối tượng. Context hỗ trợ hoàn tác/làm lại thông qua NSUndoManager tích hợp, cho phép triển khai bản nháp và hủy hành động mà không cần lưu ảnh chụp nhanh trạng thái thủ công. Khi gọi save(), context cam kết tất cả các thay đổi trong một giao dịch duy nhất vào kho lưu trữ bền vững, đảm bảo tính nguyên tử và nhất quán của dữ liệu.

Mô hình dữ liệu: Entity, Attributes, Relationships

Mô hình dữ liệu Core Data được định nghĩa trong tệp .xcdatamodeld — trình chỉnh sửa trực quan của Xcode nơi tất cả Entity, thuộc tính và mối quan hệ được mô tả. Khi biên dịch, mô hình được tuần tự hóa thành .momd và được tải qua NSManagedObjectModel.

Entity và Attributes

Entity là mô tả kiểu dữ liệu, tương tự như một bảng trong SQL. Mỗi Entity chứa một tập hợp Attributes — các trường có tên với kiểu dữ liệu (String, Integer, Date, Boolean, Data). Không giống như Room, Core Data yêu cầu chọn kiểu rõ ràng cho mỗi thuộc tính thông qua trình chỉnh sửa mô hình.

Relationships

Relationship là kết nối giữa các Entity, tương tự như khóa ngoại trong SQL. Core Data hỗ trợ tất cả các loại mối quan hệ: một-một, một-nhiều và nhiều-nhiều. Mỗi mối quan hệ có Delete Rule được cấu hình (Cascade, Nullify, Deny) — hành vi khi xóa đối tượng liên quan.

Delete RuleHành vi khi xóaVí dụ sử dụng
CascadeXóa tất cả đối tượng liên quanXóa đơn hàng cùng với các mục
NullifyĐặt mối quan hệ ngược thành nullXóa tác giả mà không xóa sách
DenyChặn xóa nếu có đối tượng liên quanBảo vệ khỏi việc xóa danh mục có sản phẩm

Chọn Delete Rule rất quan trọng đối với tính toàn vẹn dữ liệu: Cascade mà không kiểm tra có thể xóa một phần ba cơ sở dữ liệu, trong khi Deny có thể chặn hoạt động với lỗi không rõ ràng. Trong mã sản xuất, nên sử dụng Nullify với xử lý bản ghi mồ côi thủ công.

Trong trình chỉnh sửa mô hình Xcode, nhà phát triển có thể định nghĩa không chỉ Entity và thuộc tính, mà còn constraints (ràng buộc duy nhất), chỉ mục để tăng tốc truy vấn và giá trị mặc định cho thuộc tính. Tất cả các thay đổi mô hình được biên dịch thành tệp .momd, được tải trong quá trình khởi tạo NSPersistentContainer. Việc tạo phiên bản mô hình (Model Versioning) cho phép duy trì nhiều phiên bản lược đồ và thực hiện di chuyển giữa chúng.

Ngăn xếp Core Data: PersistentContainer và Context

NSPersistentContainer là một đối tượng duy nhất quản lý ngăn xếp Core Data từ iOS 10 và macOS 10.12. Nó đóng gói NSManagedObjectModel, NSPersistentStoreCoordinator và NSManagedObjectContext, tự động hóa việc tải mô hình và cấu hình kho lưu trữ. Đối với các phiên bản cũ hơn, ngăn xếp được xây dựng thủ công, nhưng điều này không còn được khuyến nghị.

swift
let container = NSPersistentContainer(name: "DataModel")
container.loadPersistentStores { _, error in
    if let error { fatalError("Core Data load failed: \(error)") }
}
let context = container.viewContext

viewContext là context chính gắn với luồng chính. Tất cả các lần đọc và cập nhật UI được thực hiện thông qua nó. Để có hiệu suất, nên thực hiện ghi dữ liệu trên context con nền với đồng bộ hóa sau đó.

NSPersistentStoreCoordinator

Bộ điều phối NSPersistentStoreCoordinator kết nối mô hình với bộ nhớ vật lý trên đĩa. Core Data hỗ trợ nhiều loại kho lưu trữ: SQLite (khuyến nghị), Binary và In-Memory. Kho lưu trữ SQLite hỗ trợ di chuyển, sao lưu gia tăng và khả năng chống sự cố trong quá trình ghi.

NSFetchRequest và làm việc với dữ liệu

NSFetchRequest là một đối tượng mô tả truy vấn đến kho lưu trữ Core Data. Nó chứa tên Entity, vị từ lọc, bộ mô tả sắp xếp và cài đặt tìm nạp. Truy vấn được thực thi qua context.fetch(), trả về một mảng NSManagedObject.

swift
let request = NSFetchRequest<User>(entityName: "User")
request.predicate = NSPredicate(format: "age >= %d", 18)
request.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)]
request.fetchLimit = 50

let results = try context.fetch(request)

NSPredicate hỗ trợ các điều kiện phức tạp: LIKE, IN, BETWEEN, CONTAINS[c] (không phân biệt hoa thường), SUBQUERY cho truy vấn lồng nhau trên Entity liên quan. Core Data cũng hỗ trợ NSFetchedResultsController — một lớp để tải dữ liệu phản ứng trong UITableView, tự động theo dõi các thay đổi và cập nhật bảng với các phần được hoạt ảnh.

Core Data trong môi trường đa luồng

Làm việc với Core Data trong ứng dụng đa luồng yêu cầu tuân thủ nghiêm ngặt các quy tắc: NSManagedObject không thể được truyền trực tiếp giữa các luồng. Mỗi luồng (hoặc hàng đợi) phải sử dụng context riêng của nó. Cách tiếp cận chính là tạo NSManagedObjectContext con với hàng đợi riêng (NSPrivateQueueConcurrencyType) để ghi và viewContext để đọc.

Context con lưu vào context cha, sau đó context cha lưu vào kho lưu trữ đĩa. Điều này đảm bảo rằng các thay đổi không chặn luồng chính và UI luôn thấy trạng thái nhất quán thông qua mergeChanges hoặc cập nhật viewContext tự động khi lưu.

Core Data sử dụng faulting — một cơ chế tải chậm cho các đối tượng liên quan. Khi tìm nạp User mà không yêu cầu địa chỉ của họ, các đối tượng Address liên quan không được tải cho đến khi chúng được truy cập qua ký hiệu dấu chấm. Faulting tiết kiệm bộ nhớ và tăng tốc tải, nhưng có thể gây ra truy cập đĩa không mong muốn trên luồng chính nếu không kiểm soát truy cập trong các context nền.

Để đa luồng hiệu quả, hãy sử dụng NSBatchInsertRequest và NSBatchDeleteRequest để chèn và xóa hàng loạt mà không tải đối tượng vào bộ nhớ — điều này rất quan trọng để đồng bộ hóa dữ liệu với máy chủ.

Các thao tác hàng loạt thực thi trực tiếp ở cấp NSPersistentStoreCoordinator, bỏ qua context và đồ thị đối tượng. Điều này cho phép chèn 10.000 bản ghi trong mili giây mà không tạo 10.000 phiên bản NSManagedObject trong bộ nhớ. Sau khi thực hiện yêu cầu hàng loạt, context phải được cập nhật qua mergeChangesFromContextDidSaveNotification để UI phản ánh dữ liệu mới. Apple khuyến nghị các thao tác hàng loạt cho việc tải dữ liệu ban đầu và đồng bộ hóa qua đêm với máy chủ.

Để theo dõi thay đổi trong Core Data, NSPersistentHistoryTracking được sử dụng — một cơ chế ghi lại mỗi giao dịch (chèn, cập nhật, xóa) trong một lịch sử riêng biệt. Bật theo dõi lịch sử cho phép đồng bộ hóa dữ liệu giữa các tiến trình và ứng dụng khác nhau làm việc với cùng một tệp SQLite, ví dụ giữa ứng dụng chính và Notification Service Extension. Kích hoạt được thực hiện qua NSPersistentStoreDescription với cờ persistentHistoryTrackingKey, và đọc qua NSPersistentHistoryChangeRequest với lọc theo ngày và loại giao dịch.

Để gỡ lỗi và phân tích hiệu suất Core Data, công cụ Core Data Profiler từ bộ Instruments trong Xcode trên macOS được sử dụng. Nó hiển thị tất cả các thao tác tìm nạp, chèn, xóa và lưu với thời lượng của mỗi thao tác và số lượng đối tượng được tải trong các bảng và biểu đồ dòng thời gian. Nhà phát triển có thể xác định các khu vực có vấn đề: nhiều lần tìm nạp cùng một truy vấn (thiếu bộ nhớ đệm), rò rỉ đối tượng fault khi cuộn bảng hoặc chặn luồng chính do tải đồng bộ các thực thể liên quan. Nên chạy hồ sơ trên thiết bị thực chứ không phải trên trình mô phỏng, vì hiệu suất của trình mô phỏng không phản ánh hành vi thực tế của ứng dụng trên iPhone hoặc iPad.

Câu hỏi thường gặp

Core Data khác SQLite như thế nào?

Core Data không phải là cơ sở dữ liệu, mà là một lớp quản lý đối tượng có thể sử dụng SQLite làm kho lưu trữ. Không giống như SQLite trực tiếp, Core Data theo dõi các thay đổi đối tượng, quản lý hoàn tác và cung cấp đồ thị đối tượng với faulting và bộ nhớ đệm. SQLite cung cấp nhiều quyền kiểm soát hơn đối với các truy vấn, nhưng yêu cầu viết SQL và quản lý giao dịch thủ công.

Làm thế nào để thực hiện di chuyển lược đồ Core Data?

Core Data hỗ trợ di chuyển nhẹ (Lightweight Migration) cho các thay đổi không phá hủy: thêm thuộc tính, đổi tên, đặt giá trị mặc định. Đối với các thay đổi phức tạp, Mapping Model được tạo. Di chuyển nhẹ được bật bằng cờ shouldMigrateAutomatically trong NSPersistentStoreDescription.

Có thể sử dụng Core Data với SwiftUI không?

Có, Core Data tích hợp với SwiftUI qua wrapper @FetchRequest cho các truy vấn và @ObservedObject để đăng ký thay đổi. SwiftUI tự động cập nhật View khi ManagedObject thay đổi, làm cho Core Data và SwiftUI trở thành một ngăn xếp tương thích để quản lý trạng thái.

Fault trong Core Data là gì?

Fault là một trình giữ chỗ nhẹ trong đồ thị Core Data không chứa dữ liệu của đối tượng liên quan. Khi fault được đặt (qua refreshObject:), dữ liệu được giải phóng khỏi bộ nhớ. Khi truy cập vào một thuộc tính, fault tự động được điền dữ liệu từ kho lưu trữ — đây là cơ chế tải chậm tối ưu hóa việc sử dụng bộ nhớ.

Làm thế nào để kiểm tra mã Core Data?

Để kiểm tra, hãy sử dụng loại kho lưu trữ In-Memory: NSPersistentStoreDescription với NSInMemoryStoreType. Container được tạo với mô hình từ gói kiểm tra. Sau mỗi bài kiểm tra, xóa tất cả đối tượng hoặc tạo lại container — điều này đảm bảo sự cách ly giữa các trường hợp kiểm tra với nhau.

Tổng kết

  • Core Data là framework quản lý đồ thị đối tượng sử dụng SQLite làm kho lưu trữ mặc định.
  • NSManagedObjectModel mô tả lược đồ: Entity, Attributes, Relationships và Delete Rules.
  • NSPersistentContainer kết hợp mô hình, bộ điều phối và viewContext thành một ngăn xếp thống nhất.
  • NSFetchRequest với NSPredicate và NSSortDescriptor tạo thành các truy vấn linh hoạt đến kho lưu trữ.
  • Đa luồng yêu cầu các context riêng biệt: context con để ghi và viewContext để đọc.
  • Faulting trì hoãn việc tải các đối tượng liên quan cho đến lần truy cập đầu tiên, tiết kiệm bộ nhớ.
  • Lightweight Migration tự động xử lý các thay đổi lược đồ không phá hủy mà không mất dữ liệu.

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.

Thảo luận dự án

Đọc thêm