剛開始接觸IOS不久空闲,嘗試著翻譯一些博客薪鹦,積累技術扁达,與大家共享正卧。本篇內容講解的是MagicRecord的使用,是對CoreData的深度封裝跪解,原文地址:http://www.raywenderlich.com/56879/magicalrecord-tutorial-ios 歡迎大家指正炉旷,謝謝!CoreData作為Mac OS 和IOS開發(fā)數據持久化和用戶數據檢索的不可缺少的一部分已經好幾年了叉讥。為了使API對開發(fā)者更容易使用窘行,也為了App的整體化,蘋果也在不間斷的更新CoreData的API节吮。也就是說抽高,即使對于一個精通IOS開發(fā)的人CoreData依舊使用起來很困難。即使你會使用CoreData透绩,每天重復性枯燥的使用CoreData也會變得很笨重翘骂,MagicalPanda創(chuàng)建的一個第三方庫為這種工作帶來了好消息壁熄。MagicalRecord 致力于更快捷和容易的使用CoreData。MagicalRecord 使用方便碳竟,特別流行草丧。正如作者所說,MagicalRecord 致力于使CoreData的代碼更簡潔莹桅,更簡單的獲取數據昌执,并且使用最優(yōu)化的操作。他是怎么做到的呢诈泼?它提供了方便的方法懂拾,包含了CoreData使用的查詢更新等的公用模板。它的設計受到了Ruby on Rails'sActiveRecord 持續(xù)性系統的影響铐达。但這些理論已經足夠了岖赋,請跟著這篇教程來見證MagicalRecord怎樣應用。在這篇教程里瓮孙,你將會創(chuàng)建一個app唐断,該App將記錄你所喜愛啤酒的一個蹤跡。它將允許你做到以下幾個事情:1.添加你所喜愛的一種啤酒杭抠。2.評價該種啤酒脸甘。3.為該種啤酒添加一個筆記。4.記錄該種啤酒的照片----如果你有太多有意義的記錄入門? ? ? 要學習本教程偏灿,你首先要對 Core Data有基本的理解丹诀,只需要了解基礎的 Core Data教程,不需要有任何高級的了解菩混。? ? ? 如果你一點也不了解CoreData忿墅,你最好先了解下 introductory Core Data tutorial,然后再繼續(xù)閱讀本教程沮峡。? ? ? 首先疚脐,請先下載Starter Project,如果已經下載好了邢疙,請繼續(xù)棍弄,把工程跑起來,你就可以看到結果疟游。這是一個帶有添加按鈕呼畸、tableView和搜索欄(下拉table會出現)、可以按照評價或者字母排序的Segment Controller的navigation controller 颁虐。如果你點擊了增加按鈕蛮原,你講進入并且查看到啤酒的詳盡信息,如果你嘗試進入其他頁面另绩,此信息還未保存∪逶桑現在我們看一下代碼花嘶,在工程的Navigator 里面你將看到:1.此工程下的所有的ViewController2.一個ImageSaver 工具類3.稍后用來初始化數據的圖片。4.一個有一些被UI使用的圖片的Images.xcassets庫5.AMRating ---一個用來評價控制的第三方庫6.最后是MagicalRecord當你看代碼的時候蹦漠,你可能注意到了沒有 Core Data模型椭员,在AppDelegate.m里面也不包含任何啟動core data的代碼。在啟動的時候看不到CoreData對任何工程來說都是最完美的方案笛园,只要記住我們就是在使用CoreData的路上隘击。使用MagicalRecord開發(fā)? ? ? ? 在工程的Navigator欄里面展開MagicalRecord 文件夾,在這個文件夾里面你將會看見Categories 和Core文件夾以及CoreData+MagicalRecord.h文件研铆。展開Categories 文件夾打開 NSManagedObjectModel+MagicalRecord.h.文件你將會發(fā)現頭文件里面的方法都以 MR_作為前綴埋同。事實上如果你看完了Categories 文件夾里面所有的文件你就會注意到所有的方法都是以MR_作為前綴的。我不知道你為前綴的方式蚜印。? ? 在工程的Navigator欄里面展開Supporting Files文件夾打開BeerTracker-Prefix.pch文件莺禁,該文件是工程的預編譯文件留量,在文件里面增加如下代碼:[html] view plain copy#define MR_SHORTHAND
#import “CoreData+MagicalRecord.h”這兩行代碼使得MagicalRecord 在你的工程里面起作用窄赋。1.MR_SHORTHAND 告訴MagicalRecord 你不想在任何的MagicalRecord方法前加MR_前綴。你可以查看MagicalRecord+ShorthandSupport.m文件來查看這句話是怎么起作用的楼熄。由于這個已經超出了我們本教程討論的范圍忆绰,我們將不在這里討論它。2.通過導入CoreData+MagicalRecord.h文件可岂,你可以在你的工程里訪問MagicalRecord 的任何一個API错敢,而不用在每一個你需要用到該API的頭文件里面導入。注意:如果你想在你自己的工程里加MagicalRecord 缕粹,在 GitHub page上有一些小貼士稚茅。你也可以按照我在項目里面? ? ? ? ? 加MagicalRecord 的方式來添加。1.從GitHub上面下載MagicalRecord 項目平斩。2.拖拽MagicalRecord 目錄到你的XCode工程亚享。3.確保CoreData.framework 包被添加進了你的工程設置里面(Build Phases\Link Binary )4.在你工程預編譯頭文件#ifdef __OBJC__代碼的下面添加如下代碼:[html] view plain copy#define MR_SHORTHAND
#import “CoreData+MagicalRecord.h”啤酒模型為了記錄你所喜愛啤酒的蹤跡,你將需要一個模型绘面,因為你不能寄希望于自己記住他們欺税,對吧?從Xcode 的菜單欄選中File\New\File…揭璃,在列表的左邊選中Core Data 并且從選項里面選中Data Model晚凿。把文件命名為 BeerModel.xcdatamodeld ,放到BeerTracker 文件夾里面瘦馍。在工程的導航欄里面選中剛創(chuàng)建的文件 BeerModel.xcdatamodeld來編輯歼秽。增加一個名字為Beer的實體(entity ),增加一個類型為String名字為Name的屬性情组。 再增加一個名字為BeerDetails的實體燥筷,這個實體將記錄啤酒的詳細信息扛吞。例如:用戶評價、筆記和在哪里找到圖片荆责。用相應的類型給BeerDetails增加下列的屬性滥比。Attribute: image Type: StringAttribute: note Type: StringAttribute: rating Type: Integer 16下一步你將創(chuàng)建這兩個實體之間的關系(RelationShip),讓Beer 實體能夠知道那個BeerDetails實例隸屬于自己做院。在BeerDetails實體下面創(chuàng)建一個新的關系(relationship )盲泛,命名為“beer”,以Beer為目的(destination) 键耕,通過選擇目標“beer”實體寺滚,你將建立這兩個實體之間的第一部分關系。通過選擇Beer實體來完成建立這個關系屈雄。增加一個命名為beerDetails的關系村视,以BeerDetails為目的(destination)與上面的Beer相對應。現在你的Beer 實體將有一個BeerDetails 實體來對應自己酒奶。下一步是創(chuàng)建類文件來展示實體蚁孔,這一步你將用到XCode,但是由于Xcode操作的一些怪癖惋嚎,你需要細心些杠氢。首先在XCode工程的導航欄里面通過選中Core Data模型來編輯它。確保你在ENTITIES 面板里面高亮了Beer實體-------而不是BeerDetails 實體另伍。下一步是在XCode的菜單欄里面執(zhí)行Editor\Create NSManagedObject Subclass… 檢查BeerModel鼻百,然后選擇下一步。然后管理上面的實體摆尝,選擇Beer和BeerDetail的復選框温艇,如果沒有被默認選中,雙擊確認Beer 是高亮的堕汞。點擊下一步勺爱,并且創(chuàng)建,然后就會生成和上面創(chuàng)建的Beer 和BeerDetails 實體相對應的兩個類臼朗。留意一下新建的這兩個類邻寿,你就會發(fā)現每個類都有和你剛剛定義的實體屬性相對應的屬性。? ? 特別留意下视哑,檢查下代表兩個實體關系的屬性绣否,你就會發(fā)現Beer類擁有 BeerDetails * 類型的一個變量beerDetails ,你還將看到BeerDetails 類有一個NSManagedObject*類型的命名為beer的變量挡毅,為什么不是 Beer * 類型的屬性呢蒜撮?這是因為在Xcode里面“Create NSManagedObject Subclass”命令的一個限制。這對該工程沒有什么影響,因此忽略它吧段磨。注意:被好奇心折磨著取逾,總是考慮為什么不創(chuàng)建一個 Beer * 類型的變量,看起來苹支,這貌似是Xcode里面CreateNSManagedObjectSubclass命令的限制砾隅。自從Xcode有了Core Data Model,這個命令就應該合乎情理的推斷出在彼此的關系里债蜜,每一個類的屬性都應該包含其他類的類型晴埂。然而這個命令不止用來生成類的屬性,也被用來生成用來定義這些類型的類的名稱寻定,而這個命令并沒有智能到來吧兩件事情都處理好儒洛。一個解決方案是簡單的調整一下生成代碼,給確定的類設置屬性狼速。另一個解決方案是讓XCode少做一些事琅锻,如果你在生成類代碼之前已經很明確的在Data Model Inspector里面定義了類名,XCode將生成正確的類屬性向胡。如果你很好奇Xcode怎么從數據模型生成代碼恼蓬,你可以查看mogenerator現在你已經創(chuàng)建了Object數據類。是時候初始化 Core Data堆棧了捷枯。打開AppDelegate.m文件滚秩,在application:didFinishLaunchingWithOptions:方法里面,在return代碼前加上下面內容:[objc] view plain copy// Setup CoreData with MagicalRecord? // Step 1. Setup Core Data Stack with Magical Record? // Step 2. Relax. Why not have a beer? Surely all this talk of beer is making you thirsty…? [MagicalRecord setupCoreDataStackWithStoreNamed:@"BeerModel"];? 如果你以前創(chuàng)建過Core Data類型的Xcode工程淮捆,你很可能知道在AppDelegate 里面初始化Core Data需要多少行代碼。而使用MagicalRecord你只需要一行代碼本股。MagicalRecord提供了一些可選的方法來建立你的Core Data堆棧攀痊,可以通過下面的步驟:1.你的后備存儲類型。2.你是否需要自動遷移拄显。3.你的Core Data 模型的名字苟径。如果你的模型文件和你的工程有一樣的基本名稱,(比如模型文件的名字是BeerTracker.xcdatamodeld躬审,工程名字是:BeerTracker)然后你就可以使用MagicalRecord的下列3個方法棘街,setupCoreDataStack, setupCoreDataStackWithInMemoryStore,或者setupAutoMigratingCoreDataStack.使用名字中有AutoMigrating的方法,你可以改變你的模型承边,并且可能自動遷移你的存儲遭殉,MagicalRecord 將幫你操縱這些。通常情況下Core Data則需要你手動添加代碼來操作你對模型的一些改變博助。調制Beer實體現在你的Core Data模型堆棧已經創(chuàng)建起來了险污,你可以向list里面添加Beer對象了。打開BeerViewController.h文件,在@class AMRatingControl后面加:[objc] view plain copy@class Beer;? 然后在@interface后面添加一個Beer屬性:[objc] view plain copy@property (nonatomic, strong) Beer *beer;? 然后切換到BeerViewController.m,然后在頂部導入 Beer.h 和BeerDetails.h[objc] view plain copy#import "Beer.h"? #import "BeerDetails.h"? 在viewDidLoad里面加入以下代碼:[objc] view plain copy- (void)viewDidLoad {? ? ? // 1. If there is no beer, create new Beer? ? ? if (!self.beer) {? ? ? ? ? self.beer = [Beer createEntity];? ? ? }? ? ? // 2. If there are no beer details, create new BeerDetails? ? ? if (!self.beer.beerDetails) {? ? ? ? ? self.beer.beerDetails = [BeerDetails createEntity];? ? ? }? ? ? // View setup? ? ? // 3. Set the title, name, note field and rating of the beer? ? ? self.title = self.beer.name ? self.beer.name : @"New Beer";? ? ? self.beerNameField.text = self.beer.name;? ? ? self.beerNotesView.text = self.beer.beerDetails.note;? ? ? self.ratingControl.rating = [self.beer.beerDetails.rating integerValue];? ? ? [self.cellOne addSubview:self.ratingControl];? ? ? ? // 4. If there is an image path in the details, show it.? ? ? if ([self.beer.beerDetails.image length] > 0) {? ? ? ? ? // Image setup? ? ? ? ? NSData *imgData = [NSData dataWithContentsOfFile:[NSHomeDirectory() stringByAppendingPathComponent:self.beer.beerDetails.image]];? ? ? ? ? [self setImageForBeer:[UIImage imageWithData:imgData]];? ? ? }? }? 故障檢測:如果你把上面的代碼貼到你的工程里面報錯了蛔糯,按快捷鍵Shift+Command+K? Clean你的工程拯腮。當BeerViewController 加載時,那是因為你有:1.或者選擇beer或者蚁飒。动壤。。2.從MasterViewController 選擇添加按鈕當視圖加載好后淮逻,你將做以下事情:1.檢查beer 實例是否加載好狼电,若沒有,這意味你將新建一個Beer2.如果beer沒有任何的BeerDetails弦蹂,創(chuàng)建一個BeerDetails對象肩碟。3.為了建立視圖,抓取beer的名字評價及筆記內容凸椿,如果beer沒有名字(在Beer的新實例里面削祈,它將給名字為“New Beer”)4.如果Beer包含了一個圖片路徑,將加載該圖片到UIImageView里面脑漫。為了編輯和添加新的beers髓抑,還有一些事情需要你建立,首先你需要能夠編輯和添加名字优幸,像如下方式編輯textFieldDidEndEditing:[objc] view plain copy- (void)textFieldDidEndEditing:(UITextField *)textField {? ? ? if ([textField.text length] > 0) {? ? ? ? ? self.title = textField.text;? ? ? ? ? self.beer.name = textField.text;? ? ? }? }? 現在你將結束添加名字吨拍,然后你就可以把beer的名字在文本框內輸入為任何內容,只要不空.為了薄脆筆記內容到 beer的筆記值里面,找到textViewDidEndEditing:方法,向如下編輯[objc] view plain copy- (void)textViewDidEndEditing:(UITextView *)textView {? ? ? [textView resignFirstResponder];? ? ? if ([textView.text length] > 0) {? ? ? ? ? self.beer.beerDetails.note = textView.text;? ? ? }? }? 下一步確保用戶在View Controller里面改變評價,beer的評價會自動更新.在updateRating里面添加:[objc] view plain copy- (void)updateRating {? ? ? self.beer.beerDetails.rating = @(self.ratingControl.rating);? }? 當用戶在詳情頁面點擊UIImageView,將允許他們添加或者編輯一張圖片.一個UIActionSheet 將會展示出來,它將允許用戶下哦那個相機膠卷選擇照片,或者拍一張新的照片.如果用戶想拍照片,你得確保照片已經保存在磁盤上了.不是吧照片保存在Core Data里面(這將導致性能問題),而是保存在用戶的文件目錄里面.你只需把圖片路徑保存在CoreData里面.通過實現UIImagePickerControllerDelegate 方法,在照片和圖庫之間管理互動,你需要在UIImagePickerController里面實現BeerViewController 委派,用來在故事板里面操縱視圖.找到imagePickerController:didFinishPickingMediaWithinfo,添加如下代碼:[objc] view plain copy- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {? ? ? // 1. Grab image and save to disk? ? ? UIImage *image = info[UIImagePickerControllerOriginalImage];? ? ? ? ? // 2. Remove old image if present? ? ? if (self.beer.beerDetails.image) {? ? ? ? ? [ImageSaver deleteImageAtPath:self.beer.beerDetails.image];? ? ? }? ? ? // 3. Save the image? ? ? if ([ImageSaver saveImageToDisk:image andToBeer:self.beer]) {? ? ? ? ? [self setImageForBeer:image];? ? ? }? ? ? [picker dismissViewControllerAnimated:YES completion:nil];? }? 下面講解下上面的代碼:1.imagePickerController:didFinishPickingMediaWithInfo:間接的傳遞了用戶選擇圖片的一個參數,,圖片是在信息字典里面的,key是UIImagePickerControllerOriginalImage2.如果Beer圖像已經包含了一個圖片,程序將把它從硬盤刪除.因此你并不會把用戶的存儲占滿.3.接著新的圖片被保存到硬盤,路徑被添加到了BeerDetails 的圖片屬性里面.打開? ImageSaver 找到saveImageToDisk:andToBeer 看一下? 是什么樣子.一旦圖片被成功保存,將會在UIImageView里面展現出來4.選擇器消失.為了使上面的修改器作用,你將修改ImageSaver ,現在你已經創(chuàng)建了Beer 類,你可以取消import行和設置圖片路徑行的注釋.打開ImageSaver.m,修改導入語句如下:[objc] view plain copy#import "ImageSaver.h"? #import "Beer.h"? #import "BeerDetails.h"? 現在你需要取消有if語句這行的注釋[objc] view plain copyif ([imgData writeToFile:jpgPath atomically:YES]) {? ? ? ? ? beer.beerDetails.image = path;? }? ImageSaver 類已經做好準備來接受圖片了.并且保存圖片到手機的文件目錄里面.保存路徑到BeerDetails 從這里開始用戶有兩個選擇,取消或完成,當你創(chuàng)建一個視圖,Beer實體就被創(chuàng)建了网杆,然后插入到managedObjectContext里面羹饰。取消則會刪除Beer 對象。找到cancelAdd碳却,加入如下代碼;[objc] view plain copy- (void)cancelAdd {? ? ? [self.beer deleteEntity];? ? ? [self.navigationController popViewControllerAnimated:YES];? }? MagicalRecord 提供了一個好的方法來刪除實體---從MagicalRecord 里面移出該實體队秩。刪除之后用戶將返回到beers的主列表。如果用戶選擇完成昼浦,將保存beer 并返回到主列表馍资。找到addNewBeer,它將簡單的pop出view controller关噪,返回到列表鸟蟹。當視圖消失時將調用viewWillDisapper,然后將輪流調用saveContext現在saveContext 是空的使兔,因此你需要添加代碼來保存新的實體建钥。向saveContext:添加如下代碼:[objc] view plain copy- (void)saveContext {? ? ? [[NSManagedObjectContext defaultContext] saveToPersistentStoreWithCompletion:^(BOOL success, NSError *error) {? ? ? ? ? if (success) {? ? ? ? ? ? ? NSLog(@"You successfully saved your context.");? ? ? ? ? } else if (error) {? ? ? ? ? ? ? NSLog(@"Error saving context: %@", error.description);? ? ? ? ? }? ? ? }];? }? 接下來,還有幾行代碼要做火诸,在 In AppDelegate.m, 里面用 MagicalRecord建立? Core Data堆棧锦针,這將創(chuàng)建一個app全局可用的默認的managedObjectContext? 對象。當你創(chuàng)建了 Beer 和BeerDetails 實體,他們就被插入到defaultContext 里面了奈搜。MagicalRecord 允許你保存任何你可能是使用saveToPersistentStoreWithCompletion: 的managedObjectContext 悉盆。若保存失敗完成的塊里面講給你一個NSError。這里你已經添加了一個簡單的if/else塊來打印出保存defaultContext時發(fā)生的問題馋吗。你想測試一下結果嗎焕盟?繼續(xù)運行你的app,選擇+按鈕宏粤,填滿內容脚翘,選擇完成。這樣做之后绍哎,在列表的頂部你沒有發(fā)現新建的Beer来农,不要急,沒問題崇堰,你將學會怎樣調整問題沃于。你可能發(fā)現調試器里面有遺傳信息。與你所說的相反海诲,你成功了繁莹!? Magical調試器當app啟動時,在 Core Data 堆棧啟動期間MagicalRecord 打印出信息特幔,這說明Core Data 正在啟動咨演。然后創(chuàng)建了defaultContext. 對象。這和我們前文提到的你保存beer 對象的是同一個defaultContext. 當你用MagicalRecord選擇完成或者保存時蚯斯,又會出現一系列Log薄风,當你保存時你將看到如下log信息:1、defaultContext 保存到主線程溉跃。2村刨、任何上下文的父類都將保存,以標志1設計撰茎。3、最后的log顯示MagicalRecord 知道兩個對象(Beer 和BeerDetail)都將保存打洼,并且被成功保存龄糊。MagicalRecord 為你打印出了很多l(xiāng)og,如果你有問題募疮,或者有些事情的表現出乎你的意料炫惩,你應該檢查日志,來獲得有用信息阿浓。注意:雖然我不推薦這莫做他嚷,如果你一定想看到發(fā)生什么情況當取消掉MagicalRecord 的日志打印。你可以在MagicalRecord.h, 的17行吧:[objc] view plain copy#define MR_ENABLE_ACTIVE_RECORD_LOGGING 1? 改成[objc] view plain copy#define MR_ENABLE_ACTIVE_RECORD_LOGGING 0? Noch ein Bier, bitte(不會翻譯)如果應用程序值得所做的工作,你將需要看到你所添加的beers 筋蓖。打開MasterViewController.m在頂部導入 Beer.h,和 BeerDetails.h為了得到所有保存在Core Data的Beer卸耘,你需要做一些事,viewWillAppear:,里面粘咖,在調用 reloadData.之前添加fetch方法蚣抗。[objc] view plain copy- (void)viewWillAppear:(BOOL)animated {? ? ? [super viewWillAppear:animated];? ? ? // Check if the user's sort preference has been saved.? ? ? ...? ? ? [self fetchAllBeers];? ? ? [self.tableView reloadData];? }? 當視圖第一次加載時,或者從查看或添加beer返回時瓮下,將獲取和加載所有的beers 到列表中翰铡。找到fetchAllBeers, 加入下列代碼:[objc] view plain copy- (void)fetchAllBeers {? ? ? // 1. Get the sort key? ? ? NSString *sortKey = [[NSUserDefaults standardUserDefaults] objectForKey:WB_SORT_KEY];? ? ? // 2. Determine if it is ascending? ? ? BOOL ascending = [sortKey isEqualToString:SORT_KEY_RATING] ? NO : YES;? ? ? // 3. Fetch entities with MagicalRecord? ? ? self.beers = [[Beer findAllSortedBy:sortKey ascending:ascending] mutableCopy];? }? MasterViewController 允許用戶通過評價來排序Beer---從5星到一星,或通過字母排序(A-Z)排序讽坏,當App第一次啟動時锭魔,創(chuàng)建一個NSUserDefault 來通過評價排序,并且作為默認建立起來路呜。在這個方法里面你做如下事情:1迷捧、檢索在NSUserDefault 保存的用來排序的key值。2拣宰、如果排序key是”rating“党涕,上升的變量設為否,如果是字幕的變量為是巡社。3膛堤、進行提取沒錯這里做的就這莫多。再來一次晌该,你在使用MagicalRecord 的方法和CoreData交互肥荔,findAllSortedBy:ascending 只是用MagicalRecord 執(zhí)行查找Core Data 實體中眾多方法中的一種,其他的還有(注意:之后你將用到):findAllInContext: –找到上下文提供的所有類型的實體 findAll – 找到現在線程上下文對象的所有實體findAllSortedBy:ascending:inContext: –和之前使用的類似但是限制了提供的上下文對象findAllWithPredicate: – 允許你傳遞謂語動詞來搜尋實體朝群。findAllSortedBy:ascending:withPredicate:inContext: – 允許傳遞升序標志來排序燕耿,允許一個特別的上下文,還允許傳遞一個謂語動詞來過濾結果集其實還有許多優(yōu)點姜胖,----看一下:NSManagedObject+MagicalFinders.m.為了在單元里添加beer的名稱和評價誉帅,找到configureCell:atIndex:,添加下列代碼:[objc] view plain copy- (void)configureCell:(UITableViewCell*)cell atIndex:(NSIndexPath*)indexPath {? ? ? // Get current Beer? ? ? Beer *beer = self.beers[indexPath.row];? ? ? cell.textLabel.text = beer.name;? ? ? ? ? // Setup AMRatingControl? ? ? AMRatingControl *ratingControl;? ? ? if (![cell viewWithTag:20]) {? ? ? ? ? ratingControl = [[AMRatingControl alloc] initWithLocation:CGPointMake(190, 10) emptyImage:[UIImage imageNamed:@"beermug-empty"] solidImage:[UIImage imageNamed:@"beermug-full"] andMaxRating:5];? ? ? ? ? ratingControl.tag = 20;? ? ? ? ? ratingControl.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;? ? ? ? ? ratingControl.userInteractionEnabled = NO;? ? ? ? ? [cell addSubview:ratingControl];? ? ? } else {? ? ? ? ? ratingControl = (AMRatingControl*)[cell viewWithTag:20];? ? ? }? ? ? // Put beer rating in cell? ? ? ratingControl.rating = [beer.beerDetails.rating integerValue];? }? 現在,再找到 prepareForSegue:sender:, 在if語句里檢查如果segue標識符是“editBeer,” 添加:[objc] view plain copyif ([[segue identifier] isEqualToString:@"editBeer"]) {? ? ? NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];? ? ? Beer *beer = self.beers[indexPath.row];? ? ? upcoming.beer = beer;? }? 這將把Beer對象傳遞給BeerViewController, 因此就可以展示beer的詳細信息右莱,允許編輯等蚜锨。繼續(xù)把你的工程跑起來:這次你將看到你之前添加的Beer和它的評價,你還可以選擇Beer并且編輯信息慢蜓,當你返回時亚再,列表就更新了。試著查看某一個Beer晨抡,不要編輯信息氛悬,返回主列表则剃,看一下log信息你將看到: -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x8b6bfa0) NO CHANGES IN ** DEFAULT ** CONTEXT - NOT SAVING當你離開詳情頁,你在viewWillDisappear:. 里面所寫的代碼將保存默認上下文如捅。然而如果沒有變化棍现, MagicalRecord 識別到沒有必要執(zhí)行一個保存操作,因此它跳過了執(zhí)行伪朽。這樣做的好處就是轴咱,你沒有必要考慮你是否應該保存,只需要嘗試保存烈涮,讓 MagicalRecord 給你指出就可以了朴肺。完成觸摸這還有一些你想讓app給用戶做的事情,比如刪除Beer坚洽,列出你喜愛啤酒的列表戈稿,執(zhí)行查詢。刪除在 MasterViewController.m,里面找到tableView:commitEditingStyle:forRowAtIndexPath:, 方法添加如下代碼:[objc] view plain copy- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {? ? ? if (editingStyle == UITableViewCellEditingStyleDelete) {? ? ? ? ? Beer *beerToRemove = self.beers[indexPath.row];? ? ? ? ? // Remove Image from local documents? ? ? ? ? if (beerToRemove.beerDetails.image) {? ? ? ? ? ? ? [ImageSaver deleteImageAtPath:beerToRemove.beerDetails.image];? ? ? ? ? }? ? ? ? ? // Deleting an Entity with MagicalRecord? ? ? ? ? [beerToRemove deleteEntity];? ? ? ? ? [self saveContext];? ? ? ? ? [self.beers removeObjectAtIndex:indexPath.row];? ? ? ? ? [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];? ? ? }? }? 記住這里調用了saveContext.方法讶舰,你需要添加一些代碼來確保刪除通過鞍盗,你已經做過一次了,你能指出怎么做嗎跳昼?準備般甲。。鹅颊。開始敷存!添加如下代碼來保存上下文[objc] view plain copy// Save ManagedObjectContext using MagicalRecord? [[NSManagedObjectContext defaultContext] saveToPersistentStoreAndWait];? 嚴格來說你沒必要知道它什么時候結束,你可以使用MagicalRecord 的其他方式來保存managedObjectContext堪伍。把App跑起來锚烦,刪除一個Beer(使用傳統的刪除cell的方式)如果你重啟App,beer就消失了帝雇。你做的很對涮俄,保存了我們的更改。這意味著你已經正確的使用了 MagicalRecord尸闸。拍拍肩膀彻亲,放松下。Demo數據給用戶一些初始化的數據吮廉,用戶就會很容易明白怎么記錄自己喜歡的啤酒睹栖,這樣會更好。在 AppDelegate.m里面導入 Beer.h, BeerDetails.h. 當建立 Core Data堆棧之后加入以下代碼:[objc] view plain copy// Setup App with prefilled Beer items.? if (![[NSUserDefaults standardUserDefaults] objectForKey:@"MR_HasPrefilledBeers"]) {? ? ? // Create Blond Ale? ? ? Beer *blondAle = [Beer createEntity];? ? ? blondAle.name? = @"Blond Ale";? ? ? blondAle.beerDetails = [BeerDetails createEntity];? ? ? blondAle.beerDetails.rating = @4;? ? ? [ImageSaver saveImageToDisk:[UIImage imageNamed:@"blond.jpg"] andToBeer:blondAle];? ? ? ? // Create Wheat Beer? ? ? Beer *wheatBeer = [Beer createEntity];? ? ? wheatBeer.name? = @"Wheat Beer";? ? ? wheatBeer.beerDetails = [BeerDetails createEntity];? ? ? wheatBeer.beerDetails.rating = @2;? ? ? [ImageSaver saveImageToDisk:[UIImage imageNamed:@"wheat.jpg"] andToBeer:wheatBeer];? ? ? ? // Create Pale Lager? ? ? Beer *paleLager = [Beer createEntity];? ? ? paleLager.name? = @"Pale Lager";? ? ? paleLager.beerDetails = [BeerDetails createEntity];? ? ? paleLager.beerDetails.rating = @3;? ? ? [ImageSaver saveImageToDisk:[UIImage imageNamed:@"pale.jpg"] andToBeer:paleLager];? ? ? ? // Create Stout? ? ? Beer *stout = [Beer createEntity];? ? ? stout.name? = @"Stout Lager";? ? ? stout.beerDetails = [BeerDetails createEntity];? ? ? stout.beerDetails.rating = @5;? ? ? [ImageSaver saveImageToDisk:[UIImage imageNamed:@"stout.jpg"] andToBeer:stout];? ? ? ? // Save Managed Object Context? ? ? [[NSManagedObjectContext defaultContext] saveToPersistentStoreWithCompletion:nil];? ? ? ? // Set User Default to prevent another preload of data on startup.? ? ? [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"MR_HasPrefilledBeers"];? ? ? [[NSUserDefaults standardUserDefaults] synchronize];? }? 在本教程的開始你下載的啟動ap茧痕,包含了4張灰白色的啤酒照片。在這里你只需要創(chuàng)建4種不同的啤酒恼除,然后保存它們踪旷。在NSUserDefaults 里面保存?zhèn)€標志曼氛,確保應用里面預先填好數據模型當應用程序第一次啟動的時候。再次運行應用程序令野,現在你就可以看到所有的新啤酒了舀患。嘗試刪除一個,然后重新運行Ap气破,然后刪掉的那個就消失了聊浅。如果你想再一次看到那幾個啤酒,從設備里面刪除應用现使,重新運行應用就可以了低匙。搜索現在你已經有超過一種的啤酒,可以測試一下搜索的功能碳锈,啟動Ap已經包含了一個搜索欄顽冶,滑動到列表的頭部就可以看到。你所需要做的僅僅是添加搜索啤酒的邏輯售碳。之前你使用過MagicalRecord 的一個方法來獲取所有種類的啤酒强重。然后她僅僅簡單的返回了所有品種的啤酒,現在你需要在所有啤酒里面檢索特殊種類的啤酒贸人。要做到這一點你需要用到謂語動詞间景。之前教程已經講解了一個使用謂語動詞檢索的方法。----你能猜出來怎么做嗎艺智?邏輯代碼在MasterViewController.m 的doSearch 方法里面倘要。[objc] view plain copy- (void)doSearch {? ? ? // 1. Get the text from the search bar.? ? ? NSString *searchText = self.searchBar.text;? ? ? // 2. Do a fetch on the beers that match Predicate criteria.? ? ? // In this case, if the name contains the string? ? ? self.beers = [[Beer findAllSortedBy:SORT_KEY_NAME ascending:YES withPredicate:[NSPredicate predicateWithFormat:@"name contains[c] %@", searchText] inContext:[NSManagedObjectContext defaultContext]] mutableCopy];? ? ? // 3. Reload the table to show the query results.? ? ? [self.tableView reloadData];? }? 再次運行Ap將啤酒列表頁面向下拽,一直到出現搜索欄力惯。在列表欄里面搜索(列表里有的和沒有的)碗誉,你得到想要的結果了嗎?從這之后干什么但愿父晶,MagicalRecord 教程能夠展示給你使用MagicalRecord 有多么的容易哮缺。學會這個樣板真的很有用。你在教程里面探索的原理能夠幫你開發(fā)各種ap甲喝,來幫助用戶記錄他們喜歡的圖片尝苇,筆記,和評價埠胖。多享受翱妨铩!你可以下載完整的代碼在這個鏈接直撤,如果你卡在哪里這將很有幫助非竿。如果你想進一步開發(fā)這個工程,下面是一些想法:1谋竖、在MasterViewController 里面添加“還沒創(chuàng)建啤酒”的提示红柱。-----檢查并使用MagicalRecord 里面的hasAtLeastOneEntity方法器联。2阻肩、添加消息提示有多少啤酒匹配搜索條件,使用countOfEntitiesWithPredicate: 方法。3竟宋、完善數據庫重置功能-----查看MagicalRecord里面的truncateAll 方法缀拭。4谆吴、如果有興趣打開 MagicalRecordShorthand.h 閱讀以下里面的方法是名稱----大部分方法的名字都很容易理解煎谍,這個頭文件應該會給你一些怎么使用MagicalRecord的一些更好的想法。如果你對本教程有任何問題隶症,或者有任何評論政模,請加入下面的討論。初次翻譯沿腰,錯誤之處還請諒解.? 完整例子代碼見:http://download.csdn.net/detail/dongtaochen2039/8139455頂5踩0? 上一篇tomcat下解決 iOS7.1企業(yè)應用"無法安裝應用程序 因為證書無效"的問題下一篇IOS后臺運行我的同類文章IOS(2)?IOS UIScrollView的自動布局2014-12-05閱讀9216?IOS后臺運行2014-11-28閱讀7100猜你在找iOS開發(fā)從入門到精通(Xcode8和Swift3)精通iOS移動開發(fā)(Xcode7&Swift2;) 初識Xcode7.0iOS移動開發(fā)從入門到精通(Xcode7 & Swift2)iOS8開發(fā)技術(Swift版):iOS基礎知識精通iOS移動開發(fā)(Xcode7&Swift2;):視圖與視圖控制器undefined reference to stdios_baseInitInitIOS開發(fā)報錯之Undefined symbols for architecture armv6ios build時Undefined symbols for architecture xxx問題的總結IOS成長之路-Undefined symbols for architecture armv7s解決之道iOS undefined symbols for architecture x86_64 查看評論7樓 qq_32560651 2016-05-23 10:39發(fā)表 [回復]樓主辛苦了,翻譯的很好啊,學到很多東西呢6樓 南之倩倩 2015-10-16 15:13發(fā)表 [回復]setupAutoMigratingCoreDataStack 數據庫遷移怎么用览徒?5樓 wjn19910224 2015-10-06 17:51發(fā)表 [回復]為什么你的刪除會崩,我照著你的打的確不崩呢颂龙。4樓 qq_16548849 2015-08-22 22:40發(fā)表 [回復]翻譯的很好 贊一個 qq :596201463 加個好友3樓 圓咕隆咚的妞妞 2015-07-03 11:39發(fā)表 [回復]寫的很好~~2樓 Soldier_cy 2015-06-09 16:51發(fā)表 [回復]非常感謝1樓 zzking321 2015-02-06 20:23發(fā)表 [回復]thx您還沒有登錄,請[登錄]或[注冊]* 以上用戶言論只代表其個人觀點习蓬,不代表CSDN網站的觀點或立場核心技術類目全部主題 Hadoop AWS 移動游戲 Java Android iOS Swift 智能硬件 Docker OpenStack VPN Spark ERP IE10 Eclipse CRM JavaScript 數據庫 Ubuntu NFC WAP jQuery BI HTML5 Spring Apache .NET API HTML SDK IIS Fedora XML LBS Unity Splashtop UML components Windows Mobile Rails QEMU KDE Cassandra CloudStack FTC coremail OPhone CouchBase 云計算 iOS6 Rackspace Web App SpringSide Maemo Compuware 大數據 aptech Perl Tornado Ruby Hibernate ThinkPHP HBase Pure Solr Angular Cloud Foundry Redis Scala Django Bootstrap個人資料 訪問我的空間 DarrenChen 訪問:36311次積分:357等級: 排名:千里之外原創(chuàng):4篇轉載:0篇譯文:2篇評論:11條文章搜索文章分類java 設計模式(2)IOS(3)文章存檔2014年12月(1)2014年11月(1)2014年10月(1)2014年03月(1)2013年04月(2)閱讀排行IOS MagicRecord 詳解(17341)IOS UIScrollView的自動布局(9209)IOS后臺運行(7095)tomcat下解決 iOS7.1企業(yè)應用"無法安裝應用程序 因為證書無效"的問題(1771)設計模式之橋接模式(376)設計模式之工廠模式(277)評論排行IOS MagicRecord 詳解(7)IOS后臺運行(2)IOS UIScrollView的自動布局(2)設計模式之工廠模式(0)設計模式之橋接模式(0)tomcat下解決 iOS7.1企業(yè)應用"無法安裝應用程序 因為證書無效"的問題(0)推薦文章* Chromium擴展(Extension)機制簡要介紹和學習計劃* Android官方開發(fā)文檔Training系列課程中文版:APP的內存管理* 程序員,別了校園入了江湖* RxJava 合并組合兩個(或多個)Observable數據源* 探索Android軟鍵盤的疑難雜癥最新評論IOS MagicRecord 詳解qq_32560651: 樓主辛苦了,翻譯的很好啊,學到很多東西呢IOS后臺運行c3812600: AVPlayerActionAtItemEndAdvance 這句實現不了重復播放措嵌, 我通過se...IOS MagicRecord 詳解南之倩倩: setupAutoMigratingCoreDataStack 數據庫遷移怎么用躲叼?IOS MagicRecord 詳解wjn19910224: 為什么你的刪除會崩,我照著你的打的確不崩呢企巢。IOS MagicRecord 詳解qq_16548849: 翻譯的很好 贊一個 qq :596201463 加個好友IOS MagicRecord 詳解圓咕隆咚的妞妞: 寫的很好~~IOS MagicRecord 詳解Soldier_cy: 非常感謝IOS后臺運行raphae000: 贊 真心好文章IOS MagicRecord 詳解zzking321: thxIOS UIScrollView的自動布局DarrenChen: 你的層級改成scrollview->view->label,然后label再用相對于view的bot...公司簡介|招賢納士|廣告服務|銀行匯款帳號|聯系方式|版權聲明|法律顧問|問題報告|合作伙伴|論壇反饋網站客服雜志客服微博客服webmaster@csdn.net400-600-2320|北京創(chuàng)新樂知信息技術有限公司 版權所有|江蘇樂知網絡技術有限公司 提供商務支持京 ICP 證 09002463 號|Copyright ? 1999-2016, CSDN.NET, All Rights Reserved GongshangLogo