【iOS】CoreData詳解

什么是CoreData

  • CoreData 不是一個數據庫但是可以使用數據庫來存儲數據,也可以使用其他方式,比如:數據庫文件,XML,二進制文件,內存等。CoreData 提供了 對象-關系映射(ORM) 功能。能夠實現數據庫數據和 OC 對象的相互轉換,在這個轉換過程中我們不需要編寫任何 SQL 語句。

  • 可以簡單的理解為Cocoa對SQLite的一層封裝

為什么要使用CoreData

  • 極大的減少Model層的代碼量

  • 優化了使用SQLite時候的性能

  • 提供了可視化設計

CoreData框架

CoreData

  • .xcdatamodeld 文件:定義了數據庫數據和 OC 對象轉換的映射關系,編譯后為 .momod 文件

  • NSManagedObjectModel:負責讀取解析 .momod 文件

  • NSPersistentStoreCoordinator:通過解析結果去實現數據庫和 OC 對象之間的相互轉換,主要是操作數據庫的,我們一般用不上,由系統處理

  • NSManagedObjectContext:等同于一個容器,用來存儲從數據庫中轉換出來的所有的 OC 對象。我們的增刪改查操作直接對這個類使用來獲得或者修改需要的 OC 對象,它能夠調用 NSPersistentStoreCoordinator 類實現對數據庫的同步

  • NSManagedObject:數據庫中的數據轉換而來的OC對象

*注:
1. 一旦數據創建完畢,就不能再修改.xcdatamodeld文件,如果有修改,必須刪除數據庫重新創建,否則打開數據庫已定會失敗。 去沙盒路徑下把創建的數據庫刪除即可
2. 不能使用alloc init來創建對象


AppDelegate.h
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow * window;

/**
  * 上下文  容器  
  * 存放的是 所有從數據庫中取出的轉換成OC對象
  */
@property (readonly, strong, nonatomic) NSManagedObjectContext * managedObjectContext;

/* 讀取解析 .momd文件中的內容 */
@property (readonly, strong, nonatomic) NSManagedObjectModel * managedObjectModel;

/* 連接的類,處理數據庫數據和OC數據底層的相互轉換 */
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator * persistentStoreCoordinator;

/* 保存 */
-(void)saveContext;

/* 獲取沙盒路徑 */
-(NSURL *)applicationDocumentsDirectory;

@end
AppDelegate.m
#import "AppDelegate.h"
#import "People.h"

@interface AppDelegate ()
@end

@implementation AppDelegate

-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSLog(@"沙盒路徑路徑:%@",[self applicationDocumentsDirectory].absoluteString);
    
    NSLog(@"%@",self.managedObjectContext);

    
    //插入一條數據 (往People表中插入一條數據)
    //NSEntityDescription 實體類
    //EntityForName 實體名稱(表名)
    People * p = [NSEntityDescription insertNewObjectForEntityForName:@"People" inManagedObjectContext:self.managedObjectContext];
    //賦值
    p.name = @"李四";
    p.age = @(25);
    p.phone = @"13667895678";
    //同步操作  把context中的數據同步到數據庫中
    [self saveContext];
    
    
    
    // 查詢數據
    // 創建查詢請求
    NSFetchRequest * request = [NSFetchRequest fetchRequestWithEntityName:@"People"];
    // Context 執行請求(執行查詢操作) 數組中存放的是oc類的對象(People類的對象)
    NSArray * array = [self.managedObjectContext executeFetchRequest:request error:nil];
    for (People *people in array)
    {
       NSLog(@"%@",people.name);
    }
    
    
    //查詢特定條件數據  (年齡>20)
    NSFetchRequest * request1 = [NSFetchRequest fetchRequestWithEntityName:@"People"];
    //使用謂詞指定查詢的判定條件
    NSPredicate * predicate = [NSPredicate predicateWithFormat:@"SELF.age > 20"];
    //關聯判定條件
    [request1 setPredicate:predicate];
    //執行查詢操作
    NSArray * array2 = [self.managedObjectContext executeFetchRequest:request1 error:nil];
    for (People * people in array2)
    {
        NSLog(@"%@",people.age);
    }
    
    

    //更改數據
    //獲取出要修改的數據
    People * people2 = [array lastObject];
    //修改屬性
    people2.name = @"123";
    people2.age  = @(30);
    //同步數據
    [self saveContext];
    


    //刪除數據
    People * people3 = [array lastObject];
    [self.managedObjectContext deleteObject:people3];
    //同步數據
    [self saveContext];
    
    return YES;
}

//點擊HOME鍵程序直接退出
-(void)applicationWillTerminate:(UIApplication *)application
{
    [self saveContext];
}

#pragma mark - Core Data stack

@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;

-(NSURL *)applicationDocumentsDirectory
{
    //獲取沙盒路徑下documents文件夾的路徑 NSURL   (類似于search)
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}

//managedObjectModel 屬性的getter方法
-(NSManagedObjectModel *)managedObjectModel
{
    if (_managedObjectModel != nil) return _managedObjectModel;

    //.xcdatamodeld文件 編譯之后變成.momd文件  (.mom文件)
    NSURL * modelURL = [[NSBundle mainBundle] URLForResource:@"CoreData_Class" withExtension:@"momd"];
    
    //把文件的內容讀取到managedObjectModel中
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    
    return _managedObjectModel;
}

//Coordinator 調度者負責數據庫的操作 創建數據庫 打開數據 增刪改查數據
-(NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (_persistentStoreCoordinator != nil) return _persistentStoreCoordinator;

    //根據model創建了persistentStoreCoordinator
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    
    // 設置數據庫存放的路徑
    NSURL * storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreData_Class.sqlite"];
    
    NSError * error = nil;
    
    //如果沒有得到數據庫,程序崩潰
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error])
    {
        NSLog(@"錯誤信息: %@, %@", error, [error userInfo]);
        abort(); //崩潰
    }
    
    return _persistentStoreCoordinator;
}

//容器類 存放OC的對象
-(NSManagedObjectContext *)managedObjectContext
{
    if (_managedObjectContext != nil)  return _managedObjectContext;
    
    NSPersistentStoreCoordinator * coordinator = [self persistentStoreCoordinator];
    if (!coordinator)
    {
        return nil;
    }
    
    //創建context對象
    _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    
    //讓context和coordinator關聯   context可以對數據進行增刪改查功能
    [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    
    return _managedObjectContext;
}

#pragma mark - Core Data Saving support

-(void)saveContext
{
    NSManagedObjectContext * managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != nil)
    {
        NSError * error = nil;

        // hasChanges 判斷數據是否更改
        // sava 同步數據庫中的數據
        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error])
        {
            NSLog(@"錯誤信息: %@, %@", error, [error userInfo]);
            abort();
        }
    }
}

@end
People.h
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@interface People : NSManagedObject

@property (nonatomic, retain) NSNumber * age;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSString * phone;

@end
People.m
#import "People.h"

@implementation People

/**
 * @property    描述對應@synthesize和@synamic兩個關鍵字
 * @synthesize  會生成屬性的setter,getter方法
 * @dynamic     不生成屬性的setter,getter方法
 * 兩個都沒有寫,默認是@synthesize
 */

@dynamic age;
@dynamic name;
@dynamic phone;

@end

參考文獻

微信公共號:iapp666666
GitHub:點此前往

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容