iOS CoreData (一) 增刪改查
Core Data是iOS5之後才出現的一個框架,提供了直接使用SQLite資料庫的大部分靈活性,它提供了物件-關係對映(ORM)的功能,即能夠將OC物件轉化成資料,儲存在SQLite資料庫檔案中,也能夠將儲存在資料庫中的資料還原成OC物件,通過CoreData管理應用程式的資料模型,可以極大程度減少需要編寫的程式碼數量!
示例Demo: CoreDataLearn

1、首先建立一個coreData 模型檔案:系統建立或者自己建立


2、在data Model 中建立專案中需要用到的實體(Entities),例如,建立一個Student 實體(第一字母必須是大寫),以及新增一些name、age、sex 等屬性,如下圖

3、生成對應實體的實體類,在此之前要注意下圖兩個設定部分,否則會引起崩潰現象





4、生成上下文 關聯資料庫
- NSManagedObjectContext 管理物件,上下文,永續性儲存模型物件,處理資料與應用的互動
- NSManagedObjectModel 被管理的資料模型,資料結構
- NSPersistentStoreCoordinator 新增資料庫,設定資料儲存的名字,位置,儲存方式
- NSManagedObject 被管理的資料記錄
- NSFetchRequest 資料請求
- NSEntityDescription 表格實體結構
①、自己建立模型檔案時需要以下程式碼來手動生成上下文,關聯資料庫
//建立資料庫 - (void)createSqlite{ //1、建立模型物件 //獲取模型路徑 NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Model" withExtension:@"momd"]; //根據模型檔案建立模型物件 NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; //2、建立持久化儲存助理:資料庫 //利用模型物件建立助理物件 NSPersistentStoreCoordinator *store = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model]; //資料庫的名稱和路徑 NSString *docStr = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; NSString *sqlPath = [docStr stringByAppendingPathComponent:@"coreData.sqlite"]; NSLog(@"資料庫 path = %@", sqlPath); NSURL *sqlUrl = [NSURL fileURLWithPath:sqlPath]; NSError *error = nil; //設定資料庫相關資訊 新增一個持久化儲存庫並設定型別和路徑,NSSQLiteStoreType:SQLite作為儲存庫 [store addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:sqlUrl options:nil error:&error]; if (error) { NSLog(@"新增資料庫失敗:%@",error); } else { NSLog(@"新增資料庫成功"); } //3、建立上下文 儲存資訊 對資料庫進行操作 NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; //關聯持久化助理 context.persistentStoreCoordinator = store; _context = context; } 複製程式碼
②、系統建立模型檔案時會自動生成關聯資料庫的程式碼,在iOS10以下和iOS10之後生成的不一樣,出現了一個新類NSPersistentContainer。
NSPersistentContainer是一個容器,封裝了應用程式中的CoreData Stack(核心資料棧堆),簡化了建立和管理的核心堆疊的資料處理建立NSManagedObjectModel,NSPersistentStoreCoordinator,NSManagedObjectContext。詳情可以看看這篇文章: blog.csdn.net/u013263917/…



AppDelegate * appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate; NSPersistentContainer * container = appDelegate.persistentContainer; //返回沙盒中儲存資料庫的資料夾URL路徑,這是一個靜態方法,表示資料庫的檔案路徑是唯一的 NSURL * url = [NSPersistentContainer defaultDirectoryURL]; NSManagedObjectContext *viewContext = container.viewContext; NSManagedObjectModel *managedObjectModel = container.managedObjectModel; NSPersistentStoreCoordinator *persistentStoreCoordinator = container.persistentStoreCoordinator; //使用儲存排程器快速在多執行緒中操作資料庫,效率非常高(比主執行緒操作塊50倍!!!) - (void)performBackgroundTask:(void (^)(NSManagedObjectContext *))block; 複製程式碼
5.增刪改查排
- 寫入資料
// 1.根據Entity名稱和NSManagedObjectContext獲取一個新的繼承於NSManagedObject的子類Student Student * student = [NSEntityDescriptioninsertNewObjectForEntityForName:@"Student"inManagedObjectContext:_context]; //2.根據表Student中的鍵值,給NSManagedObject物件賦值 student.name = [NSString stringWithFormat:@"Mr-%d",arc4random()%100]; student.age = arc4random()%20; student.sex = arc4random()%2 == 0 ?@"美女" : @"帥哥" ; student.height = arc4random()%180; student.number = arc4random()%100 //3.儲存插入的資料 NSError *error = nil; if ([_context save:&error]) { [self alertViewWithMessage:@"資料插入到資料庫成功"]; }else{ [self alertViewWithMessage:[NSString stringWithFormat:@"資料插入到資料庫失敗, %@",error]]; } 複製程式碼
- 刪除資料
- (void)deleteData{ //建立刪除請求 NSFetchRequest *deleRequest = [NSFetchRequest fetchRequestWithEntityName:@"Student"]; //刪除條件 NSPredicate *pre = [NSPredicate predicateWithFormat:@"age < %d", 10]; deleRequest.predicate = pre; //返回需要刪除的物件陣列 NSArray *deleArray = [_context executeFetchRequest:deleRequest error:nil]; //從資料庫中刪除 for (Student *stu in deleArray) { [_context deleteObject:stu]; } NSError *error = nil; //儲存--記住儲存 if ([_context save:&error]) { [self alertViewWithMessage:@"刪除 age < 10 的資料"]; }else{ NSLog(@"刪除資料失敗, %@", error); } } 複製程式碼
- 更新修改
//更新,修改 - (void)updateData{ //建立查詢請求 NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Student"]; NSPredicate *pre = [NSPredicate predicateWithFormat:@"sex = %@", @"帥哥"]; request.predicate = pre; //傳送請求 NSArray *resArray = [_context executeFetchRequest:request error:nil]; //修改 for (Student *stu in resArray) { stu.name = @"且行且珍惜_iOS"; } //儲存 NSError *error = nil; if ([_context save:&error]) { [self alertViewWithMessage:@"更新所有帥哥的的名字為“且行且珍惜_iOS”"]; }else{ NSLog(@"更新資料失敗, %@", error); } } 複製程式碼
- 讀取查詢
//讀取查詢 - (void)readData{ /* 謂詞的條件指令 1.比較運算子 > 、< 、== 、>= 、<= 、!= 例:@"number >= 99" 2.範圍運算子:IN 、BETWEEN 例:@"number BETWEEN {1,5}" @"address IN {'shanghai','nanjing'}" 3.字串本身:SELF 例:@"SELF == 'APPLE'" 4.字串相關:BEGINSWITH、ENDSWITH、CONTAINS 例:@"name CONTAIN[cd] 'ang'"//包含某個字串 @"name BEGINSWITH[c] 'sh'"//以某個字串開頭 @"name ENDSWITH[d] 'ang'"//以某個字串結束 5.萬用字元:LIKE 例:@"name LIKE[cd] '*er*'"//*代表萬用字元,Like也接受[cd]. @"name LIKE[cd] '???er*'" *注*: 星號 "*" : 代表0個或多個字元 問號 "?" : 代表一個字元 6.正則表示式:MATCHES 例:NSString *regex = @"^A.+e$"; //以A開頭,e結尾 @"name MATCHES %@",regex 注:[c]*不區分大小寫 , [d]不區分發音符號即沒有重音符號, [cd]既不區分大小寫,也不區分發音符號。 7. 合計操作 ANY,SOME:指定下列表達式中的任意元素。比如,ANY children.age < 18。 ALL:指定下列表達式中的所有元素。比如,ALL children.age < 18。 NONE:指定下列表達式中沒有的元素。比如,NONE children.age < 18。它在邏輯上等於NOT (ANY ...)。 IN:等於SQL的IN操作,左邊的表達必須出現在右邊指定的集合中。比如,name IN { 'Ben', 'Melissa', 'Nick' }。 提示: 1. 謂詞中的匹配指令關鍵字通常使用大寫字母 2. 謂詞中可以使用格式字串 3. 如果通過物件的key path指定匹配條件,需要使用%K */ //建立查詢請求 NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Student"]; //查詢條件 NSPredicate *pre = [NSPredicate predicateWithFormat:@"sex = %@", @"美女"]; request.predicate = pre; // 從第幾頁開始顯示 // 通過這個屬性實現分頁 //request.fetchOffset = 0; // 每頁顯示多少條資料 //request.fetchLimit = 6; //傳送查詢請求 NSArray *resArray = [_context executeFetchRequest:request error:nil]; [self alertViewWithMessage:@"查詢所有的美女"]; } 複製程式碼
- 排序
//排序 - (void)sort{ //建立排序請求 NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Student"]; //例項化排序物件 NSSortDescriptor *ageSort = [NSSortDescriptor sortDescriptorWithKey:@"age"ascending:YES]; NSSortDescriptor *numberSort = [NSSortDescriptor sortDescriptorWithKey:@"number"ascending:YES]; request.sortDescriptors = @[ageSort,numberSort]; //傳送請求 NSError *error = nil; NSArray *resArray = [_context executeFetchRequest:request error:&error]; if (error == nil) { [self alertViewWithMessage:@"按照age和number排序"]; }else{ NSLog(@"排序失敗, %@", error); } } 複製程式碼
CoreData除錯:
開啟Product,選擇Edit Scheme. 選擇Arguments,在下面的ArgumentsPassed On Launch中新增下面兩個選項,如圖: (1)-com.apple.CoreData.SQLDebug (2)1

示例Github: CoreDataLearn
如果需要跟我交流的話: ※ Github: github.com/wsl2ls ※ 個人部落格:wsl2ls.github.io ※ 簡書: www.jianshu.com/u/e15d1f644… ※ 微信公眾號:iOS2679114653 ※ QQ:1685527540