CoreData 是 iOS 平台強大的物件圖管理與持久化框架。本文通過完整程式碼範例,系統演示資料模型建立、上下文操作、一對多/一對一關聯配置、NSPredicate 謂詞查詢及多表連接查詢技巧。
- (void)setupCoreDataStack {
// 1. 載入資料模型
NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];
// 2. 建立持久化儲存協調器
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
// 3. 設定 SQLite 儲存路徑
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]
stringByAppendingPathComponent:@"coreData.sqlite"];
NSURL *url = [NSURL fileURLWithPath:path];
// 4. 加載持久化儲存
[psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:nil error:nil];
// 5. 建立管理物件上下文
self.context = [[NSManagedObjectContext alloc] init];
self.context.persistentStoreCoordinator = psc;
}
// 使用 NSManagedObject 子類別(推薦,支援屬性語法糖)
Student *student = [NSEntityDescription insertNewObjectForEntityForName:@"Student" inManagedObjectContext:self.context];
student.name = @"Jack";
student.age = @29;
// 建立關聯:一對多 (Teacher -> Students)
Teacher *teacher = [NSEntityDescription insertNewObjectForEntityForName:@"Teacher" inManagedObjectContext:self.context];
teacher.name = @"Li Mei";
student.teacher = teacher; // 設定反向關聯,CoreData 自動維雙向一致性
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Teacher"];
// 謂詞範例
NSPredicate *predicate = nil;
// 精確匹配
predicate = [NSPredicate predicateWithFormat:@"name == %@", @"ZhangSan"];
// 範圍查詢
predicate = [NSPredicate predicateWithFormat:@"age BETWEEN {%@, %@}", @10, @30];
// 模糊查詢
predicate = [NSPredicate predicateWithFormat:@"name LIKE %@", @"*Zhang*"];
// 組合條件
predicate = [NSPredicate predicateWithFormat:@"name == %@ AND age > %@", @"LiSi", @20];
request.predicate = predicate;
// 排序
request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]];
// 執行查詢
NSError *error = nil;
NSArray *results = [self.context executeFetchRequest:request error:&error];
// 更新:直接修改屬性後 save
teacher.name = @"Liu Wu";
// 刪除:標記刪除後 save
[self.context deleteObject:teacher];
// 查看未提交變更
NSSet *inserted = self.context.insertedObjects;
NSSet *deleted = self.context.deletedObjects;
NSSet *updated = self.context.updatedObjects;
students (To-Many),Student 實體定義 teacher (To-One),並設定為彼此的 Inverse。CoreData 不支援原生 SQL JOIN,但可透過關聯導航實現等效查詢:
// 查詢所有年齡 > 25 的學生及其老師名稱
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Student"];
request.predicate = [NSPredicate predicateWithFormat:@"age > 25"];
// 透過關聯存取:student.teacher.name
// 若需投影特定欄位,可設定 resultType = NSDictionaryResultType 並指定 propertiesToFetch
fetchBatchSize 分批載入大量資料。NSFetchedResultsController 配合 UITableView/UICollectionView 實現高效列表展示。performBlock: 在私有佇列上下文操作。reset 或重建上下文釋放記憶體壓力。