第十二課和第十三課都介紹了CoreData的知識凡桥,并在十三課的中段通過一個Demo來具體實現(xiàn)了CoreData的操作蟀伸。
筆者之前從未接觸過Core Data的相關(guān)知識,因此學期這兩節(jié)課比較吃力缅刽,這一篇總結(jié)還是有很多需要改進的地方啊掏,以后隨著對Core Data認識的深入和對這兩節(jié)課的反復咀嚼,會不斷更新該總結(jié)拷恨。
開始吧脖律!
Core Data
Core Data是一種持久化技術(shù),它能將模型對象的狀態(tài)持久化到磁盤腕侄,但它最重要的特點是:Core Data不僅是一個加載小泉、保存數(shù)據(jù)的框架,它還能和內(nèi)存中的數(shù)據(jù)很好的共事冕杠。
排除錯誤認識:Core Data并不是數(shù)據(jù)庫! 它只是連接類(Class)和數(shù)據(jù)庫(SQL)的橋梁微姊。通過Core Data的相關(guān)功能,我們可以對數(shù)據(jù)庫進行增刪改查的操作分预。
CoreData是如何工作的呢兢交?
1. 創(chuàng)建對象的可視化映射
在看到可視化映射之前,需要了解實體的概念:
實體的概念:每個實體是一個表笼痹,每個表對應一個對象配喳。
簡單粗暴的理解:實體在數(shù)據(jù)庫領域叫做表,在面向?qū)ο箢I域叫做對象凳干。
實體之間的關(guān)系=表之間創(chuàng)建關(guān)系晴裹,對象之間的關(guān)系。
注意:兩個對象之間的關(guān)系在兩個對象端具有不同的名稱救赐。而且關(guān)系的對應數(shù)量也是不同的:to one
,to many
涧团。
舉個?? :攝影者和照片的關(guān)系:
攝影者對應多個照片,但是照片只對應一個攝影者。
那么言歸正傳泌绣,如何創(chuàng)建對象的可視化映射呢?
- 創(chuàng)建模型文件元媚,用來裝入各種需要映射的實體仿滔。
- 在模型內(nèi)部添加實體(Entity)犹芹,創(chuàng)建實體之間的關(guān)系(必要時)腰埂。
下面筆者錄制了創(chuàng)建實體屿笼,增加實體屬性,連接實體的操作:
2. 為實體創(chuàng)建NSManagedObjectd子類
我們需要將剛得到的可視化的實體“轉(zhuǎn)變?yōu)椤本唧w的類杈曲。在Core Data中担扑,這些類都是NSManagedObjectd子類涌献。
下面演示一下其創(chuàng)建過程:
以實體Photo
為例燕垃,系統(tǒng)為我們生成了Photo.h
和Photo.m
卜壕。
我們先看一下Photo.h
:
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
NS_ASSUME_NONNULL_BEGIN
@interface Photo : NSManagedObject
// Insert code here to declare functionality of your managed object subclass
@end
NS_ASSUME_NONNULL_END
#import "Photo+CoreDataProperties.h"
我們可以看到印叁,
Photo
類繼承了NSManagedObject
轮蜕。
但是,有意思的是率触,系統(tǒng)還為我們自動生成了Photo+CoreDataProperties.h
和Photo+CoreDataProperties.m
葱蝗,詳情見動圖左側(cè)两曼,創(chuàng)建實體類之后玻驻。
思考:
生成這兩個文件的目的是什么呢?
首先户辫,我們首先要知道這兩個文件是什么:
他們構(gòu)成了Photo
類的分類(Category)渔欢。
那么什么是分類呢奥额?
通過分類披坏,我們可以向原有的類添加方法盐数,而不需要通過繼承的方式玫氢。分類的局限是:在分類里不能再添加屬性。
那么顯然攻旦,通過````Photo+CoreDataProperties牢屋,我們就可以不用繼承
Photo類來給其添加方法。因為原有的
Photo```類只具有屬性锋谐,除了獲取屬性之外涮拗,并不能為我們做其他的事情迂苛。這時三幻,如果可以在其他的地方給其無限地添加方法還是很具有誘惑力的赌髓。令人欣慰的是催跪,系統(tǒng)可以自動為我們生成懊蒸。
3. 通過創(chuàng)建NSManagedObjectContext訪問,操作數(shù)據(jù)庫
數(shù)據(jù)庫創(chuàng)建對象舌仍,設置對象屬性铸豁,查詢對象都需要NSManagedObjectContext
节芥。
創(chuàng)建NSManagedObjectContext
的兩個不同的方法:
1.通過其自身的初始化:
[NSManagedObjectContext alloc] init];
2.通過UIManagedDocument創(chuàng)建:
UIManagedDocument 用于管理存儲的機制头镊,將Core Data數(shù)據(jù)庫放入某存儲空間魄幕。
UIManagedDocument *document = [[UIManagedDocument alloc] initWithFileURL:url];
//url:這個core data 數(shù)據(jù)庫存儲的地方
數(shù)據(jù)庫的操作:
1. 向數(shù)據(jù)庫添加對象(實體):
[NSEntityDescription insertNewObjectForEntityForName:@"Photo" inManagedObjectContext:context];
2. 從數(shù)據(jù)庫刪除對象(實體):
[aDocument.managedObjectContext deleteObject:photo];
刪除對象后纯陨,系統(tǒng)會向所有對象發(fā)送這個消息
- (void)prepareForDeletion{
//在這里保持數(shù)據(jù)同步,比如刪掉這個對象的時候會影響到其他對象的數(shù)據(jù)
//應該在這個對象被刪除前及時更新那個數(shù)據(jù)
}
3. 在數(shù)據(jù)庫查詢對象(實體):
我們使用NSFetchRequest
類查詢數(shù)據(jù)庫的對象欲鹏,通過設置其不同屬性來查找符合不同標準的數(shù)據(jù):
舉個?? :查找出100個photo的實體:
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Photo"];
request.fetchLimit = 100;
關(guān)于Core data的線程安全
//讓context在安全隊列中執(zhí)行的方法
[context performBlock:^{
[A doSomething];
}];
NSFetchedResultsController
NSFetchedResultsController的作用是將NSFetchRequest 和 UITalbleView聯(lián)系到一起赔嚎。
和TableView的數(shù)據(jù)源方法類似:
- (NSInteger)numberOfRowsInSection:(NSInteger)section{
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return [[self.fetchedResultsController sections] count] objectAtIndex:section] numberOfObjects];
}
詳細的使用方法會在Demo講解部分中告訴大家尤误。
Demo
Demo需求
- 每隔20分鐘结缚,從flickr拿回最新的攝影者數(shù)據(jù)红竭。
- 用一個TableView顯示當前拿回的攝影者的名字和所照的照片數(shù)茵宪。
Demo效果圖
重要代碼段
1. 在啟動接口獲取flickr的數(shù)組
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.photoDatabaseContext = [self createMainQueueManagedObjectContext];
[self startFlickrFetch];
return YES;
}
- (void)startFlickrFetch
{
[self.flickrDownloadSession getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
if (![downloadTasks count]) {
NSURLSessionDownloadTask *task = [self.flickrDownloadSession downloadTaskWithURL:[FlickrFetcher URLforRecentGeoreferencedPhotos]];
task.taskDescription = FLICKR_FETCH;
[task resume];
} else {
for (NSURLSessionDownloadTask *task in downloadTasks) [task resume];
}
}];
}
2. 每隔20分鐘獲取新的內(nèi)容
- (void)setPhotoDatabaseContext:(NSManagedObjectContext *)photoDatabaseContext
{
_photoDatabaseContext = photoDatabaseContext;
//photoDatabaseContext設定成功后暖哨,每隔20分鐘重新獲取信息
if (self.photoDatabaseContext)
{
self.flickrForegroundFetchTimer = [NSTimer scheduledTimerWithTimeInterval:FOREGROUND_FLICKR_FETCH_INTERVAL
target:self
selector:@selector(startFlickrFetch:)
userInfo:nil
repeats:YES];
}
//photoDatabaseContext設定成功后 向控制器發(fā)送消息
NSDictionary *userInfo = self.photoDatabaseContext ? @{ PhotoDatabaseAvailabilityContext : self.photoDatabaseContext } : nil;
[[NSNotificationCenter defaultCenter] postNotificationName:PhotoDatabaseAvailabilityNotification
object:self
userInfo:userInfo];
}
3. 在表格視圖查詢所有攝影師的名字
- (void)setManagedObjectContext:(NSManagedObjectContext *)managedObjectContext
{
//哪個數(shù)據(jù)庫
_managedObjectContext = managedObjectContext;
NSFetchRequest *requet = [NSFetchRequest fetchRequestWithEntityName:@"Photographer"];
requet.predicate = nil;//所有的,無過濾
requet.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES selector:@selector(localizedStandardCompare:)]];
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:requet managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil];
}
4. 重寫tablelViwe:cellForRowAtIndex:
方法,顯示攝影師數(shù)據(jù)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Photographer cell"];
//拿到攝影師的名字和攝影數(shù)量
Photographer *photographer = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = photographer.name;
cell.detailTextLabel.text = [NSString stringWithFormat:@"%lu photos", [photographer.photos count]];
return cell;
}
本Demo顯然是一個未完成品达布,它只顯示了攝影師的相關(guān)信息逾冬,并且只有一個頁面粉渠。在接下來的課程中應該會對該Demo進行更多過的擴展。
最后的話
如果哪位小伙伴想拿到本文Demo的代碼請不要客氣雕沉,可以進入我的GitHub下載哦~ 這一系列到現(xiàn)在為止的所有Demo都在里面去件,分為英文注釋版本和中文注釋版本兩種。
十分歡迎給筆者的代碼和文筆拋出寶貴的意見和建議~
本文已在版權(quán)印備案倔叼,如需轉(zhuǎn)載請訪問版權(quán)印。48422928
-------------------------------- 2018年7月17日更新 --------------------------------
注意注意Aㄗ铩<什濉!
筆者在近期開通了個人公眾號框弛,主要分享編程瑟枫,讀書筆記指攒,思考類的文章幽七。
- 編程類文章:包括筆者以前發(fā)布的精選技術(shù)文章,以及后續(xù)發(fā)布的技術(shù)文章(以原創(chuàng)為主),并且逐漸脫離 iOS 的內(nèi)容咐旧,將側(cè)重點會轉(zhuǎn)移到提高編程能力的方向上铣墨。
- 讀書筆記類文章:分享編程類,思考類姚淆,心理類屡律,職場類書籍的讀書筆記超埋。
- 思考類文章:分享筆者平時在技術(shù)上,生活上的思考媒惕。
因為公眾號每天發(fā)布的消息數(shù)有限制,所以到目前為止還沒有將所有過去的精選文章都發(fā)布在公眾號上穿挨,后續(xù)會逐步發(fā)布的肴盏。
而且因為各大博客平臺的各種限制叁鉴,后面還會在公眾號上發(fā)布一些短小精干,以小見大的干貨文章哦~
掃下方的公眾號二維碼并點擊關(guān)注但壮,期待與您的共同成長~