斯坦福大學iOS開發(fā)公開課總結(jié)(十二 & 十三) :Core Data,表格視圖,F(xiàn)lickr 攝影師資料列表Demo

第十二課和第十三課都介紹了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)建對象的可視化映射呢?

  1. 創(chuàng)建模型文件元媚,用來裝入各種需要映射的實體仿滔。
  2. 在模型內(nèi)部添加實體(Entity)犹芹,創(chuàng)建實體之間的關(guān)系(必要時)腰埂。

下面筆者錄制了創(chuàng)建實體屿笼,增加實體屬性,連接實體的操作:

創(chuàng)建實體休雌,增加屬性

2. 為實體創(chuàng)建NSManagedObjectd子類

我們需要將剛得到的可視化的實體“轉(zhuǎn)變?yōu)椤本唧w的類杈曲。在Core Data中担扑,這些類都是NSManagedObjectd子類涌献。

下面演示一下其創(chuàng)建過程:

創(chuàng)建NSManagedObjectd子類

以實體Photo為例燕垃,系統(tǒng)為我們生成了Photo.hPhoto.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.hPhoto+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

獲取授權(quán)

-------------------------------- 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)注但壮,期待與您的共同成長~

公眾號:程序員維他命
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市胳施,隨后出現(xiàn)的幾起案子舞肆,更是在濱河造成了極大的恐慌,老刑警劉巖椿胯,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件前方,死亡現(xiàn)場離奇詭異廉油,居然都是意外死亡,警方通過查閱死者的電腦和手機班巩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門趣竣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人遥缕,你說我怎么就攤上這事单匣。” “怎么了码秉?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵转砖,是天一觀的道長鲸伴。 經(jīng)常有香客問我汞窗,道長仲吏,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任誓斥,我火速辦了婚禮岖食,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘析珊。我一直安慰自己,他們只是感情好惧浴,可當我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布捐腿。 她就那樣靜靜地躺著茄袖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪宪祥。 梳的紋絲不亂的頭發(fā)上蝗羊,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天耀找,我揣著相機與錄音野芒,去河邊找鬼。 笑死复罐,一個胖子當著我的面吹牛效诅,可吹牛的內(nèi)容都是我干的乱投。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼戚炫,長吁一口氣:“原來是場噩夢啊……” “哼双肤!你這毒婦竟也來了钮惠?” 一聲冷哼從身側(cè)響起素挽,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎耙箍,沒想到半個月后辩昆,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡物喷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年卤材,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片峦失。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡扇丛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出尉辑,到底是詐尸還是另有隱情帆精,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布隧魄,位于F島的核電站卓练,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏购啄。R本人自食惡果不足惜狮含,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧坑填,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間狡逢,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工低葫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人窒盐。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓葡粒,卻偏偏與公主長得像卿嘲,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子梅肤,可洞房花燭夜當晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容