1. 程式人生 > >IOS 資料儲存之 Core Data詳解

IOS 資料儲存之 Core Data詳解

  Core Date是ios3.0後引入的資料持久化解決方案,它是是蘋果官方推薦使用的,不需要藉助第三方框架。Core Date實際上是對SQLite的封裝,提供了更高階的持久化方式。在對資料庫操作時,不需要使用sql語句,也就意味著即使不懂sql語句,也可以操作資料庫中的資料。

  在各類應用開發中使用資料庫操作時通常都會用到 (ORM) “物件關係對映”,Core Data就是這樣的一種模式。ORM是將關係資料庫中的表,轉化為程式中的物件,但實際上是對資料中的資料進行操作。

  在使用Core Data進⾏行資料庫存取並不需要手動建立資料庫,建立資料庫的過程完全由Core Data框架自動完成,開發者需要做的就是把模型建立起來,具體資料庫的建立不需要管。簡單點說,Core Data實際上是將資料庫的建立、表的建立、物件和表的轉換等操作封裝起來,極大的簡化了我們的操作。

  Core Date與SQLite相比較,SQLite比較原始,操作比較複雜,使用的是C的函式對資料庫進行操作,但是SQLite可控性更強,並且能夠跨平臺。

  下面,讓我們一起來學習一下Core Data的簡單使用。

一、使用Core Data,新增實體和模型

  在建立專案的時候可以選擇使用Core Data,專案建立成功後,會在AppDelegate類中自動新增相關程式碼,此外,還會自動生成一個數據模型檔案JRCoreData.xcdatamodeld

 

AppDelegate.h

//  AppDelegate.h
//  JRCoreData
// // Created by jerei on 15-6-24. // Copyright (c) 2015年 jerehedu. All rights reserved. // #import <UIKit/UIKit.h> #import <CoreData/CoreData.h> @interface AppDelegate : UIResponder <UIApplicationDelegate> @property (strong, nonatomic) UIWindow *window; @property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext; @property (
readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel; @property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator; - (void)saveContext; - (NSURL *)applicationDocumentsDirectory; @end

AppDelegate.m

//  AppDelegate.m
//  JRCoreData
//
//  Created by jerei on 15-6-24.
//  Copyright (c) 2015年 jerehedu. All rights reserved.
//

#import "AppDelegate.h"

@interface AppDelegate ()

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application {
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}

- (void)applicationWillTerminate:(UIApplication *)application {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    // Saves changes in the application's managed object context before the application terminates.
    [self saveContext];
}

#pragma mark - Core Data stack

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

- (NSURL *)applicationDocumentsDirectory {
    // The directory the application uses to store the Core Data store file. This code uses a directory named "com.jerehedu.JRCoreData" in the application's documents directory.
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}

- (NSManagedObjectModel *)managedObjectModel {
    // The managed object model for the application. It is a fatal error for the application not to be able to find and load its model.
    if (_managedObjectModel != nil) {
        return _managedObjectModel;
    }
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"JRCoreData" withExtension:@"momd"];
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return _managedObjectModel;
}

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
    // The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it.
    if (_persistentStoreCoordinator != nil) {
        return _persistentStoreCoordinator;
    }
    
    // Create the coordinator and store
    
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"JRCoreData.sqlite"];
    NSError *error = nil;
    NSString *failureReason = @"There was an error creating or loading the application's saved data.";
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
        // Report any error we got.
        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];
        // Replace this 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();
    }
    
    return _persistentStoreCoordinator;
}


- (NSManagedObjectContext *)managedObjectContext {
    // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.)
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }
    
    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (!coordinator) {
        return nil;
    }
    _managedObjectContext = [[NSManagedObjectContext alloc] init];
    [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    return _managedObjectContext;
}

#pragma mark - Core Data Saving support

- (void)saveContext {
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != nil) {
        NSError *error = nil;
        if ([managedObjectContext hasChanges] && ![managedObjectContext 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();
        }
    }
}

@end

  如果專案在建立的時候沒有選擇使用Core Data,但是在後面需要使用,那麼需要手動的新增AppDelegate中的相關程式碼。此外,還需要手動新增一個Data Model檔案

 

  建立Data Model檔案時需要注意,檔名稱要與AppDelegate.m中managedObjectModel方法中提到的檔名稱相匹配。

  有了Data Model檔案後,就可以在裡面新增實體和關係,實際上就是向資料庫中新增表格和建立表格之間的關聯。新增實體如圖所示:

 

  每個學生有一個所在的班級,每個班級中有多個學生,因此,學生和班級之間可以建立關係。建立關係如圖所示:

 

  建立關係之後,可以切換顯示的樣式,以圖表的方式檢視實體之間的關係,如圖所示:

 

  完成上述步驟,資料庫中表格的建立就已經完成,和使用SQLite比較,省略了sql語句以及呼叫C函式操作資料庫的步驟,另外,在建立實體的時候不需要設定主鍵,實體物件的屬性的型別是OC的型別,實體中其他實體物件型別是通過建立關係新增的。

  建立好實體後,可以通過新增NSManagedObject subclass檔案,系統可以自動新增實體對應的資料模型類,如圖所示:

 

二、通過程式碼實現資料庫的操作

  1、 向學生表中插入一條資料

  在使用Core Data的時候,AppDelegate中添加了NSManagedObjectContext物件,需要獲得這個管理物件的上下文來進行操作。在操作的過程中,需要得到NSManagedObject實體,然後通過kvc設定實體的屬性值,最後通過上下文呼叫save方法儲存資料。

- (void)insert {
    
    AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
    
    //1. 獲得context
    NSManagedObjectContext *context = delegate.managedObjectContext;
    //2. 找到實體結構,並生成一個實體物件
    /*
     NSEntityDescription實體描述,也就是表的結構
     引數1:表名字
     引數2:例項化的物件由誰來管理,就是context
     */
    NSManagedObject *stu = [NSEntityDescription insertNewObjectForEntityForName:@"Student" inManagedObjectContext:context];
    
    NSManagedObject *class1 = [NSEntityDescription insertNewObjectForEntityForName:@"Classes" inManagedObjectContext:context];
    [class1 setValue:[NSNumber numberWithInt:1] forKey:@"c_id"];
    [class1 setValue:@"一班" forKey:@"c_name"];
    
    //3. 設定實體屬性值
    [stu setValue:[NSNumber numberWithInt:1] forKey:@"s_id"];
    [stu setValue:@"jerehedu" forKey:@"s_name"];
    [stu setValue:class1 forKey:@"s_class"];
    
    //4. 呼叫context,儲存實體,如果沒有成功,返回錯誤資訊
    NSError *error;
    if ([context save:&error]) {
        NSLog(@"save ok");
    }
    else
    {
        NSLog(@"%@",error);
    }
}

  2、查詢學生表中全部資料

查詢與插入資料操作類似,但是多了構造查詢物件的步驟,查詢得到結果集是一個數組,遍歷陣列,可以取出查詢資料。

- (void)selectAll {
    AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
    
    NSManagedObjectContext *context = delegate.managedObjectContext;
    
    NSEntityDescription *stu = [NSEntityDescription entityForName:@"Student" inManagedObjectContext:context];
    
    //構造查詢物件
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:stu];
    
    //執行查詢,返回結果集
    NSArray *resultAry = [context executeFetchRequest:request error:nil];
    
    //遍歷結果集
    for (NSManagedObject *enity in resultAry) {
        NSLog(@"id=%i name=%@ class=%@",[[enity valueForKey:@"s_id"] intValue],[enity valueForKey:@"s_name"],[[enity valueForKey:@"s_class"] valueForKey:@"c_name"]);
    }
}

  3、查詢指定條件的學生資訊,並更新

  指定條件的查詢除了需要構造查詢物件,還需要把查詢的條件用謂詞表示。然後遍歷查詢結果陣列中的資料,進行更行,並儲存。

- (void)update
{
    //    更新 (從資料庫找到-->更新)
    AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
    NSManagedObjectContext *context = delegate.managedObjectContext;
    
    NSEntityDescription *stu = [NSEntityDescription entityForName:@"Student" inManagedObjectContext:context];
    
    NSFetchRequest *request = [NSFetchRequest new];
    [request setEntity:stu];
    
    //構造查詢條件,相當於where子句
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"s_id=%i",1];
    
    //把查詢條件放進去
    [request setPredicate:predicate];
    
    //執行查詢
    NSArray *studentAry = [context executeFetchRequest:request error:nil];
    if (studentAry.count>0)
    {
        //更新裡面的值
        NSManagedObject *obj = studentAry[0];
        [obj setValue:@"apple" forKey:@"s_name"];
    }
    [context save:nil];
    
    //顯示
    [self selectAll];
}

  4、刪除指定條件的學生資訊

  刪除之前首先需要根據條件進行查詢,查詢到資料後刪除,並儲存。

- (void)delete
{
    //刪除 先找到,然後刪除
    AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
    NSManagedObjectContext *context = delegate.managedObjectContext;
    
    NSEntityDescription *stu = [NSEntityDescription entityForName:@"Student" inManagedObjectContext:context];
    
    NSFetchRequest *request = [NSFetchRequest new];
    [request setEntity:stu];
    
    //構造查詢條件,相當於where子句
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"s_id=%i",1];
    
    //把查詢條件放進去
    [request setPredicate:predicate];
    //執行查詢
    NSManagedObject *obj = [[context executeFetchRequest:request error:nil] lastObject];
    //刪除
    if (obj) {
        [context deleteObject:obj];
        [context save:nil];
    }
    
    [self selectAll];
}
三、小結

  Core Data是蘋果官方推薦使用的資料持久化方式,在使用的過程中,不需要匯入資料庫框架,也不需要使用sql語句操作資料庫,完全是按照面向物件的思想,使用實體模型來操作資料庫。在使用的過程中需要注意的是,如果模型發生了變化,可以選擇重新生成實體類檔案,但是自動生成的資料庫並不會自動更新,需要考慮重新生成資料庫,並把之前資料庫中資料進行移植。Core Data能夠簡化操作,但是它不支援跨平臺使用,如果想實現跨平臺,就需要使用SQLite來進行資料持久化。

  疑問諮詢或技術交流,請加入官方QQ群:JRedu技術交流 (452379712)

作者:傑瑞教育
出處: 
本文版權歸煙臺傑瑞教育科技有限公司和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線,否則保留追究法律責任的權利。

相關推薦

IOS 資料儲存 Core Data

  Core Date是ios3.0後引入的資料持久化解決方案,它是是蘋果官方推薦使用的,不需要藉助第三方框架。Core Date實際上是對SQLite的封裝,提供了更高階的持久化方式。在對資料庫操作時,不需要使用sql語句,也就意味著即使不懂sql語句,也可以操作資料庫中的資料。   在各類應用開發中使用

IOS 資料儲存 FMDB

// ViewController.m // JRFMDB // // Created by jerehedu on 15/6/18. // Copyright (c) 2015年 jerehedu. All rights reserved. // #import "ViewCon

IOS 資料儲存 SQLite

// ViewController.m // JRSQLite查詢3 // // Created by jerehedu on 15/6/16. // Copyright (c) 2015年 jerehedu. All rights reserved. // #import "Vi

Redis資料結構雜湊

簡介 Redis本身是鍵值對資料庫,但是值對應多種資料結構,其中就有雜湊(即鍵值對),值中的鍵值對稱為field和value。 基本命令 命令 命令描述 hset key field

海量資料處理Bloom Filter

一、什麼是Bloom Filter    Bloom Filter是一種空間效率很高的隨機資料結構,它的原理是,當一個元素被加入集合時,通過K個Hash函式將這個元素對映成一個位陣列(Bit array)中的K個點,把它們置為1。檢索時,我們只要看看這些點是不是都是1就(大約

android 摘要----資料儲存全方案,持久化技術

資料持久化:         只將那些記憶體中的瞬時資料儲存到儲存裝置中,保證即使在手機或電腦關機的情況下,這些資料也不會丟失。 1,檔案儲存:             是android中最基本的一種資料儲存方式,不對儲存內容進行任何格式化處理,所有詩句原封不動的儲存到檔案

iOS激情Core Data

先了解一下 Core Data 它相當於封裝了sqlite 1.Core Data 是資料持久化儲存的最佳方式,一般資料最終的儲存型別可以是:SQLite資料庫,XML,二進位制,記憶體裡,或自定義資

最全iOS資料儲存方法介紹:FMDB,SQLite3 ,Core Data,Plist,Preference偏好設定,NSKeyedArchiver歸檔,Realm

專案準備運用的Core Data進行本地資料儲存,本來打算只寫一下Core Data的,不過既然說到了資料儲存,乾脆來個資料儲存基礎大總結! 本文將對以下幾個模組進行敘述。 沙盒 Plist Preference偏好設定 NSKeyedArchiver

spring-dataspring-data-jpa:簡單三步快速上手spring-data-jpa開發

事務管理 out don 前言 map lns xid public lease 前言: 基於spring framework 4.x或spring boot 1.x開發環境 務必註意以下版本問題:Spring framework4.x(Spring boot1.x)對應s

iOS開發AddressBookUI框架

iOS開發之AddressBookUI框架詳解 一、關於AddressBookUI框架     AddressbookUI是iOS開發框架中提供的一套通訊錄介面元件。其中封裝好了一套選擇聯絡人,檢視聯絡人的介面,在需要時開發者可以直接呼叫。當然對於聯絡人介面,

iOS開發AddressBook框架

iOS開發之AddressBook框架詳解 一、寫在前面     首先,AddressBook框架是一個已經過時的框架,iOS9之後官方提供了Contacts框架來進行使用者通訊錄相關操作。儘管如此,AddressBook框架依然是一個非常優雅並且使用方便的通

iOS開發Accounts框架

iOS開發之Accounts框架詳解     Accounts框架是iOS原生提供的一套賬戶管理框架,其支援Facebook,新浪微博,騰訊微博,Twitter和領英賬戶管理的功能。需要注意,在iOS 11及以上系統中,將此功能已經刪除,因此Accounts.frame

$.ajax()data

最近在做專案的時候,用到$.ajax()進行資料互動,然後遇到一個問題,data引數中包含一個提前定義的陣列(var array=[];)這個陣列可能為空,只有符合某條件才會向其中插入元素。然後後臺接受

分散式儲存CephPG狀態

本文是滴滴雲開源框架教程系列文章的一篇。 上次分享了《Ceph介紹及原理架構分享》,這次來分享Ceph中的PG各種狀態詳解,PG是最複雜和難於理解的概念之一,PG的複雜如下: 在架構層次上,PG位於RADOS層的中間。 a. 往上負責接收和處理來自客戶端的請求

圖的儲存結構鄰接表()

之前我們介紹過圖的鄰接矩陣儲存法,它的空間和時間複雜度都是N2,現在我來介紹另外一種儲存圖的方法:鄰接表,這樣空間和時間複雜度就都是M。對於稀疏圖來說,M要遠遠小於N2。先上資料,如下。 4 5 1 4 9 4 3 8 1 2 5 2 4 6 1 3

Spark-Core應用基礎篇

一、RDD 1.什麼是RDD RDD,是spark為了簡化使用者的使用,對所有的底層資料進行的抽象,以面向物件的方式提供了RDD的很多方法,通過這些方法來對RDD進行內部的計算額輸出。 RDD:彈性分散式資料集。 2.RDD的特性 1.不可變,對於所有的RDD操作都將產生一個

資料探勘十大演算法決策樹(1)

在2006年12月召開的 IEEE 資料探勘國際會議上(ICDM, International Conference on Data Mining),與會的各位專家選出了當時的十大資料探勘演算法( top 10 data mining algorithms ),

Spark-Core應用高階篇

三、RDD高階應用 1.RDD的分片數量 def makeRDD[T: ClassTag]( seq: Seq[T], numSlices: Int = defaultParallelism): RDD[T] = withScope { paralle

資料結構圖文解析:佇列與C++模板實現

正文 回到頂部 0. 資料結構圖文解析系列 回到頂部 1. 佇列簡介 回到頂部 1.1 佇列的特點 佇列(Queue)與棧一樣,是一種線性儲存結構,它具有如下特點: 佇列中的資料元素遵循“先進先出”(First In First Out)的原則,簡稱FI

【系統學習SpringBoot】再遇Spring Data JPAJPA應用(自定義查詢及複雜查詢)

在此,對Spring Data Jpa做詳細的筆記(使用層面的,原理層日後再說哈哈。) 一、Spring Data JPA設定建立方式: 建立方式一共分為四種: #配置資料庫,使用SpringJPA spring: datasource: