iOS-CoreData詳解與使用

序言

在了解CoreData余赢,大家有必要了解對象關系映射(英語稱object Relational Mapping构眯,簡稱ORM)愕难。

ORM

ORM是通過使用描述對象和數(shù)據(jù)庫之間映射的元數(shù)據(jù)早龟,可以實現(xiàn)將對象自動持久化到關系數(shù)據(jù)庫當中惫霸。ORM的存在為了解決面向對象與數(shù)據(jù)庫科恩干存在不匹配的一種技術。

一 初識CoreData

1.CoreData是一種在iOS 3系統(tǒng)中葱弟,也是蘋果自己推出的數(shù)據(jù)存儲框架壹店,采用了一種ORM(對象關系映射)的存儲關系。

CoreData一個比較大的優(yōu)勢在于在使用CoreData過程中不需要我們編寫SQL語句芝加,也就是將OC對象存儲于數(shù)據(jù)庫硅卢,也可以將數(shù)據(jù)庫數(shù)據(jù)轉為OC對象(數(shù)據(jù)庫數(shù)據(jù)與OC對象相互轉換)。

2.CoreData幾個類

(1)NSManagedObjectContext

托管對象上下文藏杖,數(shù)據(jù)庫的大多數(shù)操作是在這個類操作

(2)NSManagedObjectModel

托管對象模型将塑,其中一個托管對象模型關聯(lián)到一個模型文件,里面存儲著數(shù)據(jù)庫的數(shù)據(jù)結構蝌麸。

(3)NSPersistentStoreCoordinator

持久化存儲協(xié)調器点寥,主要負責協(xié)調上下文玉存儲的區(qū)域的關系。

(4)NSManagedObject

托管對象類来吩,其中CoreData里面的托管對象都會繼承此類敢辩。

三 CoreData基本使用
1.gif

下面開始講解CoreData的基本使用,里面會涉及到源碼弟疆,內容比較多戚长,希望大家靜下來看完。

使用CoreData方式怠苔,有兩種可能同廉。第一種是項目開始就創(chuàng)建帶有CoreData數(shù)據(jù)庫,還有一種項目已經(jīng)開始了,重新接入CoreData恤溶,下面我們第三部分主要講述這兩種方式的過程乓诽。

1.項目開始就使用CoreData

我們在創(chuàng)建項目的時候,勾選Use Core Data

image.png

然后在文件目錄中自動生成一個后綴為.xcdatamodeld的文件

image.png

打開AppDelegate發(fā)現(xiàn)類中多了以下內容

  • AppDelegate.h
@property (readonly, strong) NSPersistentContainer *persistentContainer;

- (void)saveContext;
  • AppDelegate.m
@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:@"CoreDataDemo"];
            [_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]) {
        NSLog(@"Unresolved error %@, %@", error, error.userInfo);
        abort();
    }
}

我們可以點開testCoreData.xcdatamodeld文件咒程,我們可以看到實體和關系鸠天。如下圖

image.png

圖表說明

  • Add Entity 添加表
  • Add Attrubte 添加屬性

(1)
image.png

創(chuàng)建后可以清楚的看到模型文件左側的列表,有三個Entities帐姻、Fetch Requests以及Configurations三個選項稠集。

  • ENTITIES 實體
  • FETCH REQUESTS 請求模版
  • CONFIGURATIONS 配置信息

(2)
image.png

添加完一個實體后,你會發(fā)現(xiàn)一個實體是對應著三個內容饥瓷,分別是Attributes剥纷、Relationships和Fetched Properties。

  • Attributes 屬性
  • Relationships 關聯(lián)關系
  • Fetched Properties 獲取操作

(3)實體屬性類型

image.png

我們來分別簡單解釋類型的意義呢铆,從上往下

  • Undefined:也就是默認值晦鞋,如果參與編譯會報錯
  • Integer 16:代表整數(shù),范圍是-32768 ~ 32767
  • Integer 32:代表整數(shù)棺克,范圍是-2147483648 ~ 2147483647
  • Integer 64:代表整數(shù)悠垛,范圍是–9223372036854775808 ~ 9223372036854775807,還是很大的娜谊,較少用
  • Double:代表小數(shù)
  • Float:代表小數(shù)
  • String:代表字符串确买,NSString表示
  • Boolean:代表布爾值,使用NSNumber表示
  • Date:代表日期時期
  • Binary Data:代表二進制纱皆,是用NSData表示
  • Transformable:代表Objective對象湾趾,要遵守NSCoding協(xié)議

(4)關聯(lián)關系

image.png

點擊加號,可以添加關聯(lián)關系派草,在inverse這個屬性代表兩個實體在Relationships設置關聯(lián)關系后之后搀缠,是否可以從一個實體中找到另一個實體,這樣使兩個實體具有雙向的關聯(lián)關系近迁。

(5)Editor Style

image.png

大家通過點擊下面紅色按鈕艺普,style按鈕可以看出實體和屬性的關系,以及可以看出實體之間的對應的關系钳踊。

上面是coreData的視圖的基本運用衷敌,自己也是一個不斷摸索的過程,下面講述CoreData的基本操作拓瞪。

三 CoreData基本使用

在講述操作之前缴罗,我們首先講述NSManagedObjectContext,蘋果推薦使用initWithConcurrencyType方式創(chuàng)建祭埂,在創(chuàng)建時面氓,指定當前是什么類型的并發(fā)隊列兵钮,參數(shù)也是一個枚舉值。

NSManagedObjectContext枚舉值參數(shù)有三個類型:

  • NSConfinementConcurrencyType:此類型在iOS9之后被蘋果棄用舌界,所以不建議用這個API掘譬。
  • NSPrivateQueueConcurrencyType:代表私有并發(fā)隊列的類型,操作也是在子線程中完成的呻拌。
  • NSMainQueueConcurrencyType:代表主并發(fā)隊列類型葱轩,如果在操作過程中,需要涉及到UI操作藐握,則應該使用這個參數(shù)初始化上下文完成操作靴拱。

創(chuàng)建NSManagedObjectContext一共有兩種方法,下面分別介紹

1.下面我們以Student為模型猾普,創(chuàng)建主隊列并發(fā)類型的NSManagedObjectContext
/** NSManagedObjectContext */
@property(nonatomic, strong)NSManagedObjectContext *context;

- (NSManagedObjectContext *)context {
    if (_context == nil) {
        // 創(chuàng)建上下文對象袜炕,并發(fā)隊列設置為主隊列
        _context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
        
        // 創(chuàng)建托管對象模型,并使用Student.momd路徑當做初始化參數(shù)
        // .xcdatamodeld文件 編譯之后變成.momd文件  (.mom文件)
        NSURL *modelPath = [[NSBundle mainBundle] URLForResource:@"CoreDataDemo" withExtension:@"momd"];
        NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelPath];
        
        // 創(chuàng)建持久化存儲調度器
        NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
        
        // 創(chuàng)建并關聯(lián)SQLite數(shù)據(jù)庫文件初家,如果已經(jīng)存在則不會重復創(chuàng)建
        NSString *dataPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
        dataPath = [dataPath stringByAppendingFormat:@"/%@.sqlite",@"Student"];
        
        [coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:dataPath] options:nil error:nil];
        
        // 上下文對象設置屬性為持久化存儲器
        _context.persistentStoreCoordinator = coordinator;
    }
    return _context;
}
  • 解釋說明

(1) 將NSManagedObjectContext聲明為一個變量偎窘,并且使用懶加載的形式,方便使用溜在。

(2) .xcdatamodeld文件 編譯之后變成.momd文件陌知,所以生成NSManagedObjectModel托管對象模型的時候,文件后綴名一定要寫對炕泳。

image.png

(3) 創(chuàng)建并關聯(lián)SQLite數(shù)據(jù)庫文件纵诞,如果已經(jīng)存在則不會重復創(chuàng)建上祈。


image.png
2.使用系統(tǒng)推薦的方法創(chuàng)建
@property (readonly, strong) NSPersistentContainer *persistentContainer;

@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:@"CoreDataDemo"];
            [_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
                if (error != nil) {
                    NSLog(@"Unresolved error %@, %@", error, error.userInfo);
                    abort();
                }
            }];
        }
    }
    
    return _persistentContainer;
}

使用的時候

self.persistentContainer.viewContext
四 實戰(zhàn) - 增培遵,刪,改登刺,查
4.1 插入操作

CoreData通過NSEntityDescriptioninsert進行插入操作籽腕,這樣就會生成并返回一個托管對象,并將這個對象插入到上下文中纸俭。下面以一個Student為例:

- (Student *)insert1 {
    NSError *error = nil;
    
   // 開始創(chuàng)建托管對象皇耗,并指明好創(chuàng)建的托管對象所屬實體名
    Student * student = [NSEntityDescription insertNewObjectForEntityForName:@"Student" inManagedObjectContext:self.context];
    
    //2.根據(jù)表Student中的鍵值,給NSManagedObject對象賦值
    student.name = [NSString stringWithFormat:@"Mr-%d",arc4random() % 100];
    student.age = arc4random() % 20;
    student.sex = arc4random() % 2 == 0 ?  @"男" : @"女" ;
    student.height = arc4random() % 180;
    student.number = arc4random() % 100;
    
    if ([self.context hasChanges] && ![self.context save:&error]) {
        NSLog(@"Unresolved error %@, %@", error, error.userInfo);
        _resultLbe.text = [NSString stringWithFormat:@"CoreData Error:%@",error.userInfo];
        abort();
        return nil;
    } else {
        _resultLbe.text = @"插入數(shù)據(jù)成功";
    }
    
    return student;
}

NSManagedObjectContext將操作的數(shù)據(jù)放到了緩存層中揍很,只有調用了NSManagedObjectContextsave后郎楼,才會對數(shù)據(jù)庫進行真正的操作,否則對象僅僅存在內存中窒悔,這樣就很好地避免了數(shù)據(jù)庫的頻繁訪問呜袁。

4.2 刪除操作

CoreData首先通過獲取需要刪除的托管對象,遍歷所需要獲取的對象數(shù)組简珠,逐個刪除阶界,最后調用NSManagedObjectContextsave方法。

- (void)delete:(NSArray *)delStudents {
    // 獲取數(shù)據(jù)的請求對象,指明對實體進行刪除操作
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Student"];
    
    NSMutableArray *delStudentSucces = [NSMutableArray array];  // 保存在數(shù)據(jù)庫中成功被刪除的對象
    [delStudents enumerateObjectsUsingBlock:^(Student *obj, NSUInteger idx, BOOL *stop) {
        // 通過創(chuàng)建謂詞對象膘融,然后過濾掉符合要求的對象芙粱,也就是要刪除的對象
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"number = %d",obj.number];
        request.predicate = predicate;
        
        // 通過執(zhí)行獲取操作,找到要刪除的對象即可
        NSError *error = nil;
        NSArray<Student *> *students = [self.context executeFetchRequest:request error:&error];
        
        // 開始真正操作氧映,一一遍歷春畔,遍歷符合刪除要求的對象數(shù)組,執(zhí)行刪除操作
        [students enumerateObjectsUsingBlock:^(Student *obj, NSUInteger idx, BOOL *stop) {
            [self.context deleteObject:obj];
        }];
        
        // 錯誤處理
        if (error) {
            self.resultLbe.text = [NSString stringWithFormat:@"CoreData Error:%@",error.description];
        } else {
            [delStudentSucces addObject:obj];
        }
    }];
    
    // 最后保存數(shù)據(jù)岛都,保存上下文拐迁。
    if (self.context.hasChanges) {
        [self.context save:nil];
    }
    
    if (delStudentSucces.count > 0) {
        self.resultLbe.text = @"刪除數(shù)據(jù)成功";
    }
    
    // 將已經(jīng)在數(shù)據(jù)庫中被刪除的對象從內存中移除
    [delStudentSucces enumerateObjectsUsingBlock:^(Student *obj, NSUInteger idx, BOOL *stop) {
        [self.dataSources removeObject:obj];
    }];
    [self.tableView reloadData];
}
4.3 修改操作

將所有數(shù)據(jù)庫中的學生,性別顛倒疗绣,年齡加1操作线召。

- (void)modify:(NSArray *)modifyStudents {
    // 獲取數(shù)據(jù)的請求對象,指明對實體進行刪除操作
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Student"];
    
    NSMutableArray *modifyStudentSucces = [NSMutableArray array];
    [modifyStudents enumerateObjectsUsingBlock:^(Student *obj, NSUInteger idx, BOOL *stop) {
        // 通過創(chuàng)建謂詞對象多矮,然后過濾掉符合要求的對象缓淹,也就是要刪除的對象
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"number = %d",obj.number];
        request.predicate = predicate;
        
        // 通過執(zhí)行獲取操作,找到要刪除的對象即可
        NSError *error = nil;
        NSArray<Student *> *students = [self.context executeFetchRequest:request error:&error];
        
        // 開始真正操作塔逃,一一遍歷讯壶,遍歷符合刪除要求的對象數(shù)組,執(zhí)行刪除操作
        [students enumerateObjectsUsingBlock:^(Student *obj, NSUInteger idx, BOOL *stop) {
            obj.age += 1;
            obj.sex = [obj.sex isEqualToString:@"男"] ? @"女" : @"男";
        }];
        
        // 錯誤處理
        if (error) {
            self.resultLbe.text = [NSString stringWithFormat:@"CoreData Error:%@",error.description];
        } else {
            [modifyStudentSucces addObject:obj];
        }
    }];
    
    // 最后保存數(shù)據(jù)湾盗,保存上下文伏蚊。
    if (self.context.hasChanges) {
        [self.context save:nil];
    }
    
    if (modifyStudentSucces.count > 0) {
        self.resultLbe.text = @"修改數(shù)據(jù)成功";
    }
    
    NSArray *news = [self search];
    [self.dataSources removeAllObjects];
    [self.dataSources addObjectsFromArray:news];
    [self.tableView reloadData];
    
    self.resultLbe.text = @"修改數(shù)據(jù)成功";
}
4.4 查找操作

查找操作是是有許多條件限制,根據(jù)條件查找出相應的數(shù)據(jù)格粪,下面以一個例子說明一下(查找出所有的元素躏吊,條件以后細節(jié)會講出)

- (NSArray *)search {
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Student"];
    
    // 執(zhí)行獲取操作,獲取所有Student托管對象
    NSError *error = nil;
    NSArray<Student *> *students = [self.context executeFetchRequest:request error:&error];
    
    if (error) {
        _resultLbe.text = [NSString stringWithFormat:@"CoreData Error:%@",error.description];
    } else {
        _resultLbe.text = @"查找數(shù)據(jù)成功";
    }
    
    return students;
}

以上就是CoreData的基本使用帐萎,自己也在不斷的完善中比伏,希望上面對大家對CoreData認識會進一步提高。


本文參考 iOS-CoreData詳解與使用 ,非常感謝該作者疆导。


更多同類型文章參考
iOS-SQLite3的使用詳解
iOS-CoreData詳解與使用
iOS-FMDB詳解及使用
iOS SQLite赁项、CoreData、FMDB數(shù)據(jù)庫詳解


項目連接地址 - CoreDataDemo

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末澈段,一起剝皮案震驚了整個濱河市悠菜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌败富,老刑警劉巖悔醋,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異囤耳,居然都是意外死亡篙顺,警方通過查閱死者的電腦和手機偶芍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來德玫,“玉大人匪蟀,你說我怎么就攤上這事≡咨” “怎么了材彪?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長琴儿。 經(jīng)常有香客問我段化,道長,這世上最難降的妖魔是什么造成? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任显熏,我火速辦了婚禮,結果婚禮上晒屎,老公的妹妹穿的比我還像新娘喘蟆。我一直安慰自己,他們只是感情好鼓鲁,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布蕴轨。 她就那樣靜靜地躺著,像睡著了一般骇吭。 火紅的嫁衣襯著肌膚如雪橙弱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天燥狰,我揣著相機與錄音棘脐,去河邊找鬼。 笑死碾局,一個胖子當著我的面吹牛荆残,可吹牛的內容都是我干的奴艾。 我是一名探鬼主播净当,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蕴潦!你這毒婦竟也來了像啼?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤潭苞,失蹤者是張志新(化名)和其女友劉穎忽冻,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體此疹,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡僧诚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年遮婶,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片湖笨。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡旗扑,死狀恐怖,靈堂內的尸體忽然破棺而出慈省,到底是詐尸還是另有隱情臀防,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布边败,位于F島的核電站袱衷,受9級特大地震影響,放射性物質發(fā)生泄漏笑窜。R本人自食惡果不足惜致燥,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一笨农、第九天 我趴在偏房一處隱蔽的房頂上張望周崭。 院中可真熱鬧爽航,春花似錦堂湖、人聲如沸毫玖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽绍移。三九已至艳悔,卻和暖如春急凰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背猜年。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工抡锈, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人乔外。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓床三,卻偏偏與公主長得像,于是被迫代替她去往敵國和親杨幼。 傳聞我的和親對象是個殘疾皇子撇簿,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內容

  • 該文章屬于劉小壯原創(chuàng),轉載請注明:劉小壯[http://www.reibang.com/u/2de707c93d...
    劉小壯閱讀 19,775評論 17 149
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,100評論 1 32
  • 1 CoreData運行機制 1.1 CoreData總體架構 1.1.1 CoreData架構圖 CoreDat...
    Kevin_Junbaozi閱讀 3,660評論 2 7
  • 在今年清華經(jīng)管學院舉行的2017級本科生開學典禮上差购,清華經(jīng)管學院院長錢穎一教授和新同學們分享了喬布斯講的三個故事四瘫。...
    EC君_王磊閱讀 178評論 0 0
  • 久違的雨 淅淅瀝瀝 窗外 斜織的雨絲 洗禮著路旁的綠樹 花草也打起精神 享受著遲來的甘霖 來往的行人中 那個花傘底...
    張愛國_3a01閱讀 152評論 0 1