Core Data是有蘋果官方提供的框架(#import <CoreData/CoreData.h>
)亮蛔,實現(xiàn)數(shù)據(jù)持久化存儲。Core Data實際上是將數(shù)據(jù)庫的創(chuàng)建、表的創(chuàng)建司倚、對象和表的轉(zhuǎn)換等操作封裝起來,極大的簡化了操作篓像。使用Core Data進?數(shù)據(jù)庫存取不需要手動創(chuàng)建數(shù)據(jù)庫动知,創(chuàng)建數(shù)據(jù)庫的過程完全由Core Data框架自動完成,使用者需要做的就是把模型創(chuàng)建起來员辩。
Core Date與SQLite相比較盒粮,SQLite比較原始,操作比較復(fù)雜奠滑,使用的是C的函數(shù)對數(shù)據(jù)庫進行操作丹皱,但是SQLite可控性更強,并且能夠跨平臺宋税。
以下是Core Data操作中經(jīng)常使用的幾個類:
1摊崭、NSManagedObjectModel:被管理的對象模型,相當(dāng)于實體弃甥,不過它包含 了實體間的關(guān)系爽室。
2、NSManagedObjectContext:被管理的對象上下文淆攻,相當(dāng)于操作實際內(nèi)容 作用:插入數(shù)據(jù) 查詢 更新 刪除
阔墩。
3、NSPersistentStoreCoordinator:持久化存儲助理瓶珊,用于數(shù)據(jù)庫的連接器啸箫。
4、NSFetchRequest :獲取數(shù)據(jù)的請求伞芹,用于數(shù)據(jù)查詢忘苛,相當(dāng)于查詢語句蝉娜。
5、NSPredicate:相當(dāng)于查詢條件扎唾。
6召川、NSEntityDescription:實體結(jié)構(gòu)。下面胸遇,講解Core Data的簡單使用
在創(chuàng)建項目的時候可以選擇使用Core Data荧呐,項目創(chuàng)建成功后,在AppDelegate類中系統(tǒng)會自動添加相關(guān)代碼纸镊,此外倍阐,還會自動生成一個數(shù)據(jù)模型文件
工程名.xcdatamodeld
AppDelegate.h類中對應(yīng)生成的代碼:
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
//系統(tǒng)自動引入類
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (readonly, strong) NSPersistentContainer *persistentContainer;
- (void)saveContext;
@end
AppDelegate.m類中對應(yīng)生成的代碼,此處注意在XCode中自動生成的代碼較之前有所變動:
#pragma mark - Core Data stack
@synthesize persistentContainer = _persistentContainer;
- (NSPersistentContainer *)persistentContainer {
// The persistent container for the application. This implementation creates and returns a container, having loaded the store for the application to it.
@synchronized (self) {
if (_persistentContainer == nil) {
_persistentContainer = [[NSPersistentContainer alloc] initWithName:@"_23"];
[_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
if (error != nil) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
NSLog(@"Unresolved error %@, %@", error, error.userInfo);
abort();
}
}];
}
}
return _persistentContainer;
}
#pragma mark - Core Data Saving support
- (void)saveContext {
NSManagedObjectContext *context = self.persistentContainer.viewContext;
NSError *error = nil;
if ([context hasChanges] && ![context save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@"Unresolved error %@, %@", error, error.userInfo);
abort();
}
}
如果在創(chuàng)建項目的時候沒有勾選Use Core Data選項逗威,但是在后面需要使用峰搪,需要手動添加一個Data Model文件和手動的添加AppDelegate中的相關(guān)代碼
注:創(chuàng)建Data Model文件時需要注意,文件名稱要與AppDelegate.m中managedObjectModel方法中提到的文件名稱相匹配,ios8的Xcode排版發(fā)生了一些變動凯旭,需要注意
在生成Data Model文件后概耻,在~~.xcdatamodeld里面添加實體和關(guān)系添加實體如圖所示:
注:這里實際上就是向數(shù)據(jù)庫中添加表格和建立表格之間的關(guān)聯(lián)
完成以上步驟,數(shù)據(jù)庫中表格的創(chuàng)建就已經(jīng)完成尽纽,和使用SQLite比較咐蚯,省略了sql語句以及調(diào)用C函數(shù)操作數(shù)據(jù)庫的步驟,另外弄贿,在創(chuàng)建實體的時候不需要設(shè)置主鍵春锋,實體對象的屬性的類型是OC的類型,實體中其他實體對象類型是通過建立關(guān)系添加的差凹。
創(chuàng)建好實體后期奔,可以通過添加NSManagedObject subclass文件(注:創(chuàng)建模型對象的類, "Editor > Create NSManagedobject Subclass"。)危尿,系統(tǒng)可以自動添加實體對應(yīng)的數(shù)據(jù)模型類呐萌,如圖所示:
以下是封裝好的CoreDataManaer單例文件
#import <Foundation/Foundation.h>
@interface CoreDataManager : NSObject
/**
* 單例的初始化類方法
*
* @return CoreDataManager
*/
+ (CoreDataManager *)defaultManager;
/**
* 添加一個對象模型到數(shù)據(jù)庫中
*
* @param name 模型類的名字
* @param dictionary 需要對應(yīng)賦值的屬性
*/
- (void)addManagedObjectModelWithName:(NSString *)name dictionary:(NSDictionary *)dictionary;
/**
* 查詢對象模型
*
* @param name 模型類的名字
* @param predicate 創(chuàng)建一個謂詞
* @param sortkeys 用來排序的Keys(注意是個數(shù)組)
*
* @return 返回查到的對象, 在外部使用時應(yīng)與name對應(yīng)
*/
- (NSArray *)fetchManagedObjectModelWithName:(NSString *)name predicate:(NSPredicate *)predicate sortKeys:(NSArray *)sortkeys;
/**
* 刪除對象模型
*
* @param models 對象模型數(shù)組(注意是數(shù)組, 盡管是刪除一個也要數(shù)組)
*/
- (void)deleteAllManagedObjectModels:(NSArray *)models;
@end
#import "CoreDataManager.h"
#import <CoreData/CoreData.h>
@interface CoreDataManager ()
@property (nonatomic, strong) NSManagedObjectContext * managedObjectContext;
@property (nonatomic, strong) NSManagedObjectModel * managedObjectModel;
@property (nonatomic, strong) NSPersistentStoreCoordinator * persistentStoreCoordinator;
@end
@implementation CoreDataManager
static CoreDataManager * s_defaultManager = nil;
+ (CoreDataManager *)defaultManager {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
s_defaultManager = [[CoreDataManager alloc] init];
});
return s_defaultManager;
}
/**
* 單例的初始化方法, 在init方法中初始化單例類持有的對象
*
* @return 初始化后的對象
*/
- (instancetype)init
{
self = [super init];
if (self) {
// 添加觀察者, 當(dāng)ManagerObjectContext發(fā)生變化時調(diào)用saveContext方法
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveContext) name:NSManagedObjectContextObjectsDidChangeNotification object:nil];
}
return self;
}
- (void)addManagedObjectModelWithName:(NSString *)name dictionary:(NSDictionary *)dictionary {
NSManagedObject * managerObject = [NSEntityDescription insertNewObjectForEntityForName:name inManagedObjectContext:self.managedObjectContext];
[managerObject setValuesForKeysWithDictionary:dictionary];
}
- (NSArray *)fetchManagedObjectModelWithName:(NSString *)name predicate:(NSPredicate *)predicate sortKeys:(NSArray *)sortkeys {
// 實例化查詢請求
NSFetchRequest * fetchRequest = [NSFetchRequest fetchRequestWithEntityName:name];
// 謂詞搜索如果沒有謂詞, 那么默認查詢?nèi)? if (predicate) {
[fetchRequest setPredicate:predicate];
}
// 如果沒有用來排序的key, 那么默認不排序
if (sortkeys) {
// 如果有排序的Key就先創(chuàng)建一個數(shù)組來接收多個NSSortDescriptor對象(盡管是一個, 因為setSortDescriptors:方法需要數(shù)組作為參數(shù))
NSMutableArray * sortDescriptorKeys = [NSMutableArray new];
// 遍歷所有的用來排序的key
for (NSString * key in sortkeys) {
// 每有一個Key, 就使用該key來創(chuàng)建一個NSSortDescriptor
NSSortDescriptor * sortDescriptor = [[NSSortDescriptor alloc] initWithKey:key ascending:YES];
// 在sortDescriptorKeys數(shù)組中添加一個NSSortDescriptor元素
[sortDescriptorKeys addObject:sortDescriptor];
}
// 查詢請求設(shè)置排序方式
[fetchRequest setSortDescriptors:sortDescriptorKeys];
}
// 使用數(shù)組來接收查詢到的內(nèi)容
NSArray * fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:nil];
// 如果數(shù)組為nil
if (fetchedObjects == nil) {
// 創(chuàng)建一個新的數(shù)組返回, 在外部去做判斷
fetchedObjects = [NSArray new];
}
// 返回查找到的數(shù)組
return fetchedObjects;
}
- (void)deleteAllManagedObjectModels:(NSArray *)models {
// 遍歷刪除傳進來數(shù)組中的元素對應(yīng)的表內(nèi)容
for (NSManagedObject * object in models) {
// 使用管理者刪除對象, 數(shù)組中的元素并沒有缺少
[self.managedObjectContext deleteObject:object];
}
}
#pragma mark - Core Data stack
- (NSURL *)applicationDocumentsDirectory {
// NSLog(@"%@", [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]);
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
/**
* 模型器的懶加載方法
*
* @return 唯一的模型器
*/
- (NSManagedObjectModel *)managedObjectModel {
if (!_managedObjectModel) {
NSURL * momdPath = [[NSBundle mainBundle] URLForResource:@"PetEfamily" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momdPath];
}
return _managedObjectModel;
}
/**
* 鏈接器的懶加載方法
*
* @return 唯一的鏈接器對象
*/
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (!_persistentStoreCoordinator) {
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"LOCoreDataSample.sqlite"];
[_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:@{NSInferMappingModelAutomaticallyOption : @YES, NSMigratePersistentStoresAutomaticallyOption : @YES } error:nil];
}
return _persistentStoreCoordinator;
}
/**
* 管理者的懶加載方法
*
* @return 唯一的管理者對象
*/
- (NSManagedObjectContext *)managedObjectContext {
if (!_managedObjectContext) {
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:[self persistentStoreCoordinator]];
}
return _managedObjectContext;
}
/**
* ManagerObjectContext的保存方法
*/
- (void)saveContext {
[self.managedObjectContext save:nil];
}
@end