前言:
學習了Sqlite數據之后認真思考了一下,對於已經習慣使用orm數據庫的開發者或者對sql語句小白的開發者來說該如何做好數據庫開發呢?這個上網搜了一下?看來總李多慮了!apple 提供了一種數據方式,它就是今天的主角:CoreData!我們一起來探究它是否能夠滿足我們項目開發的需要呢?
CoreData介紹:
Core Date是ios3.0后引入的數據持久化解決方案,它是是蘋果官方推薦使用的,不需要借助第三方框架。Core Date實際上是對SQLite的封裝,提供了更高級的持久化方式。在對數據庫操作時,不需要使用sql語句,也就意味着即使不懂sql語句,也可以操作數據庫中的數據。
CoreData優點:
Core Data實際上是將數據庫的創建、表的創建、對象和表的轉換等操作封裝起來,極大的簡化了我們的操作。Core Date與SQLite相比較,SQLite比較原始,操作比較復雜,使用的是C的函數對數據庫進行操作,但是SQLite可控性更強,並且能夠跨平台。
CoreData缺點:
存儲性能一般,默認建立的表沒有主鍵,效率低,復雜的查詢更是不敢想像。CoreData 對批量數據的處理執行的不太好,查資料好像說IOS8推出了批量處理的一些方式。對於多線程的支持也不太好,我是xcode 7上開發的每一個entity都要生成4個類,打個比方一個項目中要建10個表那就要維護40個類,你說累不累?
怎么使用CoreData?
第一步:在項目中引入CoreData.framework
第二步:創建xxxx.xcdatamodeld
第三步:模型對象的實體
接下來就是具體實現:具體實現之前先來認識如下幾個對象
(1)NSManagedObjectModel(被管理的對象模型)
相當於實體,不過它包含 了實體間的關系
(2)NSManagedObjectContext(被管理的對象上下文)
操作實際內容
作用:插入數據 查詢 更新 刪除
(3)NSPersistentStoreCoordinator(持久化存儲助理)
相當於數據庫的連接器
(4)NSFetchRequest(獲取數據的請求)
相當於查詢語句
(5)NSPredicate(相當於查詢條件)
(6)NSEntityDescription(實體結構)
為了方便實現,本文整理一個數據管理類來測試CoreData:CoreDataManager
CoreDataManager.h

#import <Foundation/Foundation.h> #import <CoreData/CoreData.h> @interface CoreDataManager : NSObject<NSCopying> @property(strong,nonatomic,readonly)NSManagedObjectModel* managedObjectModel;//管理數據模型 @property(strong,nonatomic,readonly)NSManagedObjectContext* managedObjectContext;//管理數據內容 @property(strong,nonatomic,readonly)NSPersistentStoreCoordinator* persistentStoreCoordinator;//持久化數據助理 //創建數據庫管理者單例 +(instancetype)shareManager; //插入數據 -(void)insertData:(NSString*)tempName; //刪除數據 -(void)deleteData; //刪除數據 -(void)deleteData:(NSString*)tempName; //查詢數據 -(void)queryData; //根據條件查詢 -(void)queryData:(NSString*)tempName; //更新數據 -(void)updateData:(NSString*)tempName; @end
CoreDataManager.m

#import "CoreDataManager.h" #import "Car.h" static CoreDataManager *shareManager=nil; @implementation CoreDataManager @synthesize managedObjectContext =_managedObjectContext; @synthesize managedObjectModel = _managedObjectModel; @synthesize persistentStoreCoordinator = _persistentStoreCoordinator; //實例化對象 -(instancetype)init { self=[super init]; if (self) { } return self; } //創建數據庫管理者單例 +(instancetype)shareManager { //這里用到了雙重鎖定檢查 if(shareManager==nil){ @synchronized(self){ if(shareManager==nil){ shareManager =[[[self class]alloc]init]; } } } return shareManager; } -(id)copyWithZone:(NSZone *)zone { return shareManager; } +(id)allocWithZone:(struct _NSZone *)zone { if(shareManager==nil){ shareManager =[super allocWithZone:zone]; } return shareManager; } //托管對象 -(NSManagedObjectModel *)managedObjectModel { if (_managedObjectModel!=nil) { return _managedObjectModel; } NSURL* modelURL=[[NSBundle mainBundle] URLForResource:@"myCoreData" withExtension:@"momd"]; _managedObjectModel=[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; return _managedObjectModel; } //托管對象上下文 -(NSManagedObjectContext *)managedObjectContext { if (_managedObjectContext!=nil) { return _managedObjectContext; } NSPersistentStoreCoordinator* coordinator=[self persistentStoreCoordinator]; if (coordinator!=nil) { _managedObjectContext=[[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];//NSMainQueueConcurrencyType NSPrivateQueueConcurrencyType [_managedObjectContext setPersistentStoreCoordinator:coordinator]; } return _managedObjectContext; } //持久化存儲協調器 -(NSPersistentStoreCoordinator *)persistentStoreCoordinator { if (_persistentStoreCoordinator!=nil) { return _persistentStoreCoordinator; } NSString* docs=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject]; NSURL* storeURL=[NSURL fileURLWithPath:[docs stringByAppendingPathComponent:@"myCoreData.sqlite"]]; NSLog(@"path is %@",storeURL); NSError* error=nil; _persistentStoreCoordinator=[[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { NSLog(@"Error: %@,%@",error,[error userInfo]); } return _persistentStoreCoordinator; } //插入數據 -(void)insertData:(NSString*)tempName { //讀取類 Car *car=[NSEntityDescription insertNewObjectForEntityForName:@"Car" inManagedObjectContext:self.managedObjectContext]; car.name=tempName; //保存 NSError *error; [self.managedObjectContext save:&error]; } //刪除數據 -(void)deleteData { //創建讀取類 NSEntityDescription *entity =[NSEntityDescription entityForName:@"Car" inManagedObjectContext:self.managedObjectContext]; //創建連接 NSFetchRequest* request=[[NSFetchRequest alloc] init]; [request setEntity:entity]; //啟動查詢 NSError *error; NSArray *deleteArr=[self.managedObjectContext executeFetchRequest:request error:&error]; if(deleteArr.count){ for (Car *car in deleteArr) { [self.managedObjectContext deleteObject:car]; } NSError *error; [self.managedObjectContext save:&error]; }else{ NSLog(@"未查詢到可以刪除的數據"); } } //刪除數據 -(void)deleteData:(NSString*)tempName; { //創建讀取類 NSEntityDescription *entity =[NSEntityDescription entityForName:@"Car" inManagedObjectContext:self.managedObjectContext]; //創建連接 NSFetchRequest* request=[[NSFetchRequest alloc] init]; [request setEntity:entity]; //創建檢索條件 NSPredicate *predicate =[NSPredicate predicateWithFormat:@"name=%@",tempName]; [request setPredicate:predicate]; //啟動查詢 NSError *error; NSArray *deleteArr=[self.managedObjectContext executeFetchRequest:request error:&error]; if(deleteArr.count){ for (Car *car in deleteArr) { [self.managedObjectContext deleteObject:car]; } NSError *error; [self.managedObjectContext save:&error]; }else{ NSLog(@"未查詢到可以刪除的數據"); } } //查詢數據 -(void)queryData { //創建讀取類 NSEntityDescription *entity =[NSEntityDescription entityForName:@"Car" inManagedObjectContext:self.managedObjectContext]; //創建連接 NSFetchRequest* request=[[NSFetchRequest alloc] init]; [request setEntity:entity]; //啟動查詢 NSError *error; NSArray *carArr=[self.managedObjectContext executeFetchRequest:request error:&error]; for(Car *car in carArr){ NSLog(@"car---->%@",car.name); } } -(void)queryData:(NSString*)tempName { //創建讀取類 NSEntityDescription *entity =[NSEntityDescription entityForName:@"Car" inManagedObjectContext:self.managedObjectContext]; //創建連接 NSFetchRequest* request=[[NSFetchRequest alloc] init]; [request setEntity:entity]; //創建檢索條件 NSPredicate *predicate =[NSPredicate predicateWithFormat:@"name=%@",tempName]; [request setPredicate:predicate]; //啟動查詢 NSError *error; NSArray *carArr=[self.managedObjectContext executeFetchRequest:request error:&error]; for(Car *car in carArr){ NSLog(@"car---->%@",car.name); } } //更新數據 -(void)updateData:(NSString*)tempName { //創建讀取類 NSEntityDescription *entity =[NSEntityDescription entityForName:@"Car" inManagedObjectContext:self.managedObjectContext]; //創建連接 NSFetchRequest* request=[[NSFetchRequest alloc] init]; [request setEntity:entity]; //創建檢索條件 NSPredicate *predicate =[NSPredicate predicateWithFormat:@"name=%@",tempName]; [request setPredicate:predicate]; //啟動查詢 NSError *error; NSArray *deleteArr=[self.managedObjectContext executeFetchRequest:request error:&error]; if(deleteArr.count){ for (Car *car in deleteArr) { car.name=@"test"; } NSError *error; [self.managedObjectContext save:&error]; }else{ NSLog(@"未查詢到可以刪除的數據"); } } @end
具體使用方式
//清空數據 [[CoreDataManager shareManager]deleteData]; //插入10條數據 for(int i=0;i<10;i++){ NSString *string = [[NSString alloc] initWithFormat:@"%d",i]; [[CoreDataManager shareManager]insertData:string]; } //然后查詢一下 [[CoreDataManager shareManager]queryData]; //然后刪除一條數據 [[CoreDataManager shareManager]deleteData:@"5"]; //然后查詢一下 [[CoreDataManager shareManager]queryData]; // 更新數據 [[CoreDataManager shareManager]updateData:@"3"]; //然后查詢一下 [[CoreDataManager shareManager]queryData]; //清空數據 [[CoreDataManager shareManager]deleteData]; //然后查詢一下 [[CoreDataManager shareManager]queryData];
測試一下效率:測試數據10000條
NSMutableArray *testArray =[[NSMutableArray alloc]init]; int testMaxCount =10000; for(int i=0;i<testMaxCount;i++){ NSString *string = [[NSString alloc] initWithFormat:@"%d",i]; [testArray addObject:string]; } //測試一下效率 第1種 CFAbsoluteTime start = CFAbsoluteTimeGetCurrent(); for(NSString *tempName in testArray){ [[CoreDataManager shareManager]insertData:tempName]; } CFAbsoluteTime end=CFAbsoluteTimeGetCurrent(); NSLog(@"coreData數據插入 time cost: %0.3f", end - start); //測試一下效率 第2種 start = CFAbsoluteTimeGetCurrent(); [[CoreDataManager shareManager]insertDatas:testArray]; end=CFAbsoluteTimeGetCurrent(); NSLog(@"coreData數據插入 time cost: %0.3f", end - start);
insertData函數:
//插入數據 -(void)insertData:(NSString*)tempName { //讀取類 Car *car=[NSEntityDescription insertNewObjectForEntityForName:@"Car" inManagedObjectContext:self.managedObjectContext]; car.name=tempName; //保存 NSError *error; [self.managedObjectContext save:&error]; }
insertDatas函數:
//插入數據 -(void)insertDatas:(NSArray*)tempNames { for(NSString *name in tempNames){ Car *car=[NSEntityDescription insertNewObjectForEntityForName:@"Car" inManagedObjectContext:self.managedObjectContext]; car.name=name; } NSError *error; [self.managedObjectContext save:&error]; }
運行結果:
第一種:8.408
第二種:0.162
但是有個超級大的問題,第二種方式雖然效率高,但是插入數據亂序。第一種正常但是效率超低,同樣近似的數據量sqlite效率比這個高不知多少倍。如果用這個來做數據庫開發我覺得是無愛了。批量操作支持的不太好。對於它的數據庫升級也不想過多了解。所以就隨便查了下,得出如下結論:CoreData 的數據模型升級兼容性比較差,如果模型不對,會導致程序連起都起不來。雖然提供了模型升級代碼,但是在客戶端的管理模型版本管理也會相對復雜。