IOS---數據持久化(Core Data)

  • Core Data不是數據庫,⽽而是使⽤用數據庫、XML、二進制⽂文件等⽅方式來存儲數據的⼀個框架。git

  • Core Data是iOS3以後纔出現的一個框架,容許咱們以面向對象的⽅式儲存和管理數據。使⽤Core Data框架,咱們能夠很輕鬆有效地經過面向對象的接⼝管理數據。github

  • Core Data框架提供了對象-關係映射(ORM)的功能,即可以將OC對象轉化成數據,sql

  • 保存在SQLite3數據庫文件中,也可以將保存在數據庫中的數據還原成OC對象。 在數據操做過程當中,⽆需編寫任何SQL語句。數據庫

##一、CoreData核心對象:多線程

  • NSManagedObject:模型對象,或者叫實體(entity),可理解爲OC⾥裏的對象。
  • NSManagedObjectModel:模型文件(.xcdatamodeld),記錄全部的模型對象及對象 的屬性
  • NSPersistentStoreCoordinator:持久化存儲協調者,是數據庫和程序之間的橋樑, ⽤來設置數據存儲的名字,位置,存儲⽅式,和存儲時機。用來執⾏行具體的CRUD操做。
  • NSManagedObjectContext:對象管理上下文,⽤戶全部的持久化操做都是經過此對象。再由此對象去調用NSPersistentStoreCoordinator對象執⾏具體的操做。

##二、基於SQLite數據庫時,Core Data的簡單使用app

和SQLite的區別:只能取出整個實體記錄,而後分解,以後才能獲得實體的某個屬性框架

構建流程fetch

1.如果新建的工程,選擇空白應用程序,next線程

2.勾選Use Core Data選項代理

此時生成的工程文件AppDelegate中,會自動生成被管理的數據上下文等相關代碼

被管理的數據上下文 初始化的後,必須設置持久化存儲助理

- (NSManagedObjectContext *)managedObjectContext {
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }
    
    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (!coordinator) {
        return nil;
    }
    _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    return _managedObjectContext;
}

被管理的數據模型 初始化必須依賴.momd文件路徑,而.momd文件由.xcdatamodeld文件編譯而來

- (NSManagedObjectModel *)managedObjectModel {
    
    if (_managedObjectModel != nil) {
        return _managedObjectModel;
    }
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"CoreData" withExtension:@"momd"];
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return _managedObjectModel;
}

持久化存儲助理 初始化必須依賴NSManagedObjectModel,以後要指定持久化存儲的數據類型,默認的是NSSQLiteStoreType,即SQLite數據庫;並指定存儲路徑爲Documents目錄下,以及數據庫名稱

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
    
    if (_persistentStoreCoordinator != nil) {
        return _persistentStoreCoordinator;
    }
     _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreData.sqlite"];
    NSError *error = nil;
    
    NSDictionary *options = @{NSMigratePersistentStoresAutomaticallyOption:@YES,NSInferMappingModelAutomaticallyOption:@YES};
    NSString *failureReason = @"There was an error creating or loading the application's saved data.";
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
        NSMutableDictionary *dict = [NSMutableDictionary dictionary];
        dict[NSLocalizedDescriptionKey] = @"Failed to initialize the application's saved data";
        dict[NSLocalizedFailureReasonErrorKey] = failureReason;
        dict[NSUnderlyingErrorKey] = error;
        error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict];
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }
    
    return _persistentStoreCoordinator;
}

方法saveContext表示:保存數據到持久層(數據庫)

- (void)saveContext {
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != nil) {
        NSError *error = nil;
        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
            
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }
    }
}

方法applicationDocumentsDirectory表示:應用程序沙箱下的Documents目錄路徑

- (NSURL *)applicationDocumentsDirectory {
    
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}

3.若是不是新工程,也能夠本身寫入相關代碼(建立一個新的工程複製過來也行)

###2.1添加數據

得到AppDelegate的代理對象

AppDelegate *delegate = [UIApplication sharedApplication].delegate;

添加實體對象

// 建立實體對象
    // NSEntityDescription *entity = [NSEntityDescription entityForName:@"User" inManagedObjectContext:delegate.managedObjectContext];
    
    //添加一個實體對象到 managedObjectContext 中
    User *user = [NSEntityDescription insertNewObjectForEntityForName:@"User" inManagedObjectContext:delegate.managedObjectContext];
    user.userID = @10002;
    user.userName = @"懷化";
    user.userAge = @30;
    user.userSex = @"男";
    user.userDate = [NSDate date];

保存上下文:

[delegate saveContext];

###2.2查詢數據

建立一個取值請求:

NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"User"];

使用謂詞設置查詢條件:

request.predicate = [NSPredicate predicateWithFormat:@"userAge < 35"];
request.predicate = [NSPredicate predicateWithFormat:@"userName LIKE '*楊*'"];

設置查詢的條數:

request.fetchLimit = 2;

指定從某個位置開始查詢(分頁效果)

request.fetchOffset = 2;

按某個字段升序、降序排列(YES爲升序,NO爲降序)

NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"userAge" ascending:YES];
    request.sortDescriptors = @[sort];

在上下文中執行取值請求:

NSArray *objects = [delegate.managedObjectContext executeFetchRequest:request error:&error];
    
    [objects enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        
        User *user = (User *)obj;
        
        NSLog(@"%@ %@ %@ %@ %@",user.userID, user.userName, user.userAge, user.userSex, user.userDate);
    }];

###2.3 修改數據數據

查詢:

NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"User"];
    request.predicate = [NSPredicate predicateWithFormat:@"userID == '10005'"];
    
    NSArray *objects = [delegate.managedObjectContext executeFetchRequest:request error:nil];

修改:

[objects enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
   	User *user = (User *)obj;
   user.userDate = [NSDate date];
    //保存
   	[delegate saveContext];
}

###2.3刪除數據

NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"User"];
    request.predicate = [NSPredicate predicateWithFormat:@"userID == '10005'"];
    
    NSArray *objects = [delegate.managedObjectContext executeFetchRequest:request error:nil];
    
    [objects enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        
        // 二、刪除
        [delegate.managedObjectContext deleteObject:obj];
        
        // 三、保存
        [delegate saveContext];
    }];

##三、數據庫依賴關係

在存在數據的過程當中,可能會遇到一些相互之間有關聯的數據,好比一個學生有不少本書,每本書的屬性不一樣

在模型文件中,設置Relationships關係就能夠添加關聯關係

  • 設置關聯關係的Type爲To Many就是一對多的關係,To One則爲一對一

  • 設置關聯關係的 delete rule 爲 cascade 時,當刪除當前數據時所關聯的數據也會被刪除。若是爲 Nullify(默認) 就不會刪除關聯的數據

有時在操做數據比較大的狀況下,在當前線程執行會形成軟件卡頓的狀況,這時能夠運用下列方法。

多線程下執行:

[[CoreDataManager shareManager].moContext performBlock:^{
        
        [stus enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            
            Student *stu = (Student *)obj;
            
            NSLog(@"%@ %@ %@ %@ %@",stu.stuID,stu.stuName,stu.stuAge,stu.book.bookName, stu.apples);
            
            [stu.apples enumerateObjectsUsingBlock:^(Apples * _Nonnull obj, BOOL * _Nonnull stop) {
                
                Apples *apple = (Apples *)obj;
                NSLog(@"%@ %@",apple.appleName, apple.applePrice);
            }];
        }];
        
    }];
}

##四、第三方框架(MagicalRecord)使用更簡單方便快捷

下載地址:https://github.com/fuxinto/MagicalRecord

Demo下載地址:

https://github.com/fuxinto/HfxDemo

相關文章
相關標籤/搜索