剛開始接觸IOS不久,嘗試着翻譯一些博客,積累技術,與你們共享。 html
本篇內容講解的是MagicRecord的使用,是對CoreData的深度封裝,原文地址: ios
http://www.raywenderlich.com/56879/magicalrecord-tutorial-ios 歡迎你們指正,謝謝! git
CoreData做爲Mac OS 和IOS開發數據持久化和用戶數據檢索的不可缺乏的一部分已經好幾年了。爲了使API對開發者更容易使用,也爲了App的總體化,蘋果也在不間斷的更新CoreData的API。 github
也就是說,即便對於一個精通IOS開發的人CoreData依舊使用起來很困難。即便你會使用CoreData,天天重複性枯燥的使用CoreData也會變得很笨重,MagicalPanda建立的一個第三方庫爲這種工做帶來了好消息。MagicalRecord 致力於更快捷和容易的使用CoreData。 數據庫
MagicalRecord 使用方便,特別流行。正如做者所說,MagicalRecord 致力於使CoreData的代碼更簡潔,更簡單的獲取數據,而且使用最優化的操做。他是怎麼作到的呢?它提供了方便的方法,包含了CoreData使用的查詢更新等的公用模板。它的設計受到了Ruby on Rails'sActiveRecord 持續性系統的影響。
app
但這些理論已經足夠了,請跟着這篇教程來見證MagicalRecord怎樣應用。在這篇教程裏,你將會建立一個app,該App將記錄你所喜好啤酒的一個蹤影。它將容許你作到如下幾個事情:
1.添加你所喜好的一種啤酒。 ide
2.評價該種啤酒。
工具
3.爲該種啤酒添加一個筆記。 性能
4.記錄該種啤酒的照片----若是你有太多有意義的記錄 學習
入門
要學習本教程,你首先要對 Core Data有基本的理解,只須要了解基礎的 Core Data教程,不須要有任何高級的瞭解。
若是你一點也不瞭解CoreData,你最好先了解下 introductory Core Data tutorial,而後再繼續閱讀本教程。
首先,請先下載Starter Project,若是已經下載好了,請繼續,把工程跑起來,你就能夠看到結果。
這是一個帶有添加按鈕、tableView和搜索欄(下拉table會出現)、能夠按照評價或者字母排序的Segment Controller的navigation controller 。若是你點擊了增長按鈕,你講進入而且查看到啤酒的詳盡信息,若是你嘗試進入其餘頁面,此信息還未保存。
如今咱們看一下代碼,在工程的Navigator 裏面你將看到:
1.此工程下的全部的ViewController
2.一個ImageSaver 工具類
3.稍後用來初始化數據的圖片。
4.一個有一些被UI使用的圖片的Images.xcassets庫
5.AMRating ---一個用來評價控制的第三方庫
6.最後是MagicalRecord
當你看代碼的時候,你可能注意到了沒有 Core Data模型,在AppDelegate.m裏面也不包含任何啓動core data的代碼。在啓動的時候看不到CoreData對任何工程來講都是最完美的方案,只要記住咱們就是在使用CoreData的路上。
使用MagicalRecord開發
在工程的Navigator欄裏面展開MagicalRecord 文件夾,在這個文件夾裏面你將會看見Categories 和Core文件夾以及CoreData+MagicalRecord.h文件。展開Categories 文件夾打開 NSManagedObjectModel+MagicalRecord.h.文件你將會發現頭文件裏面的方法都以 MR_做爲前綴。事實上若是你看完了Categories 文件夾裏面全部的文件你就會注意到全部的方法都是以MR_做爲前綴的。我不知道你爲前綴的方式。
在工程的Navigator欄裏面展開Supporting Files文件夾打開BeerTracker-Prefix.pch文件,該文件是工程的預編譯文件,在文件裏面增長以下代碼:
- <span style="font-family:Times New Roman;font-size:14px;">#define MR_SHORTHAND
- #import 「CoreData+MagicalRecord.h」</span>
這兩行代碼使得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__代碼的下面添加以下代碼:
- <span style="font-family:Times New Roman;font-size:14px;">#define MR_SHORTHAND
- #import 「CoreData+MagicalRecord.h」</span>
啤酒模型
爲了記錄你所喜好啤酒的蹤影,你將須要一個模型,由於你不能寄但願於本身記住他們,對吧?從Xcode 的菜單欄選中File\New\File…,在列表的左邊選中Core Data 而且從選項裏面選中Data Model。
把文件命名爲 BeerModel.xcdatamodeld ,放到BeerTracker 文件夾裏面。
在工程的導航欄裏面選中剛建立的文件 BeerModel.xcdatamodeld來編輯。增長一個名字爲Beer的實體(entity ),增長一個類型爲String名字爲Name的屬性。
再增長一個名字爲BeerDetails的實體,這個實體將記錄啤酒的詳細信息。例如:用戶評價、筆記和在哪裏找到圖片。用相應的類型給BeerDetails增長下列的屬性。
- Attribute: image Type: String
- Attribute: note Type: String
- Attribute: rating Type: Integer 16
下一步你將建立這兩個實體之間的關係(RelationShip),讓Beer 實體可以知道那個BeerDetails實例隸屬於本身。在BeerDetails實體下面建立一個新的關係(relationship ),命名爲「beer」,以Beer爲目的(destination) ,經過選擇目標「beer」實體,你將創建這兩個實體之間的第一部分關係。
經過選擇Beer實體來完成創建這個關係。增長一個命名爲beerDetails的關係,以BeerDetails爲目的(destination)與上面的Beer相對應。如今你的Beer 實體將有一個BeerDetails 實體來對應本身。
下一步是建立類文件來展現實體,這一步你將用到XCode,可是因爲Xcode操做的一些怪癖,你須要細心些。
首先在XCode工程的導航欄裏面經過選中Core Data模型來編輯它。確保你在ENTITIES 面板裏面高亮了Beer實體-------而不是BeerDetails 實體。
下一步是在XCode的菜單欄裏面執行Editor\Create NSManagedObject Subclass… 檢查BeerModel,而後選擇下一步。而後管理上面的實體,選擇Beer和BeerDetail的複選框,若是沒有被默認選中,雙擊確認Beer 是高亮的。點擊下一步,而且建立,而後就會生成和上面建立的Beer 和BeerDetails 實體相對應的兩個類。留意一下新建的這兩個類,你就會發現每一個類都有和你剛剛定義的實體屬性相對應的屬性。
特別留意下,檢查下表明兩個實體關係的屬性,你就會發現Beer類擁有 BeerDetails * 類型的一個變量beerDetails ,你還將看到BeerDetails 類有一個NSManagedObject*類型的命名爲beer的變量,爲何不是 Beer * 類型的屬性呢?這是由於在Xcode裏面「Create NSManagedObject Subclass」命令的一個限制。這對該工程沒有什麼影響,所以忽略它吧。
注意:被好奇心折磨着,老是考慮爲何不建立一個 Beer * 類型的變量,看起來,這貌似是Xcode裏面CreateNSManagedObjectSubclass命令的限制。自從Xcode有了Core Data Model,這個命令就應該合乎情理的推斷出在彼此的關係裏,每個類的屬性都應該包含其餘類的類型。然而這個命令不止用來生成類的屬性,也被用來生成用來定義這些類型的類的名稱,而這個命令並無智能到來吧兩件事情都處理好。一個解決方案是簡單的調整一下生成代碼,給肯定的類設置屬性。另外一個解決方案是讓XCode少作一些事,若是你在生成類代碼以前已經很明確的在Data Model Inspector裏面定義了類名,XCode將生成正確的類屬性。
若是你很好奇Xcode怎麼從數據模型生成代碼,你能夠查看mogenerator
如今你已經建立了Object數據類。是時候初始化 Core Data堆棧了。打開AppDelegate.m文件,在application:didFinishLaunchingWithOptions:方法裏面,在return代碼前加上下面內容:
- // 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"];
若是你之前建立過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模型堆棧已經建立起來了,你能夠向list裏面添加Beer對象了。打開BeerViewController.h文件,在@class AMRatingControl後面加:
而後在
@interface後面添加一個Beer屬性:
- @property (nonatomic, strong) Beer *beer;
而後切換到
BeerViewController.m
,而後在頂部導入 Beer.h 和BeerDetails.h
- #import "Beer.h"
- #import "BeerDetails.h"
在
viewDidLoad
裏面加入如下代碼:
- - (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 實例是否加載好,若沒有,這意味你將新建一個Beer
2.若是beer沒有任何的BeerDetails,建立一個BeerDetails對象。
3.爲了創建視圖,抓取beer的名字評價及筆記內容,若是beer沒有名字(在Beer的新實例裏面,它將給名字爲「New Beer」)
4.若是Beer包含了一個圖片路徑,將加載該圖片到UIImageView裏面。
爲了編輯和添加新的beers,還有一些事情須要你創建,首先你須要可以編輯和添加名字,像以下方式編輯textFieldDidEndEditing:
- - (void)textFieldDidEndEditing:(UITextField *)textField {
- if ([textField.text length] > 0) {
- self.title = textField.text;
- self.beer.name = textField.text;
- }
- }
如今你將結束添加名字,而後你就能夠把
beer的名字在文本框內輸入爲任何內容,只要不空.
爲了薄脆筆記內容到 beer的筆記值裏面,找到textViewDidEndEditing:方法,向以下編輯
- - (void)textViewDidEndEditing:(UITextView *)textView {
- [textView resignFirstResponder];
- if ([textView.text length] > 0) {
- self.beer.beerDetails.note = textView.text;
- }
- }
下一步確保用戶在
View Controller
裏面改變評價,beer的評價會自動更新.在updateRating裏面添加:
- - (void)updateRating {
- self.beer.beerDetails.rating = @(self.ratingControl.rating);
- }
當用戶在詳情頁面點擊
UIImageView,
將容許他們添加或者編輯一張圖片.一個UIActionSheet 將會展現出來
,它將容許用戶下哦那個相機膠捲選擇照片,或者拍一張新的照片.若是用戶想拍照片,你得確保照片已經保存在磁盤上了.不是吧照片保存在
Core Data裏面(這將致使性能問題),而是保存在用戶的文件目錄裏面.你只需把圖片路徑保存在CoreData裏面.
經過實現UIImagePickerControllerDelegate 方法,在照片和圖庫之間管理互動,你須要在UIImagePickerController裏面實現BeerViewController 委派,用來在故事板裏面操縱視圖.找到imagePickerController:didFinishPickingMediaWithinfo,添加以下代碼:
- - (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是UIImagePickerControllerOriginalImage
2.若是Beer圖像已經包含了一個圖片,程序將把它從硬盤刪除.所以你並不會把用戶的存儲佔滿.
3.接着新的圖片被保存到硬盤,路徑被添加到了BeerDetails 的圖片屬性裏面.打開 ImageSaver 找到saveImageToDisk:andToBeer 看一下 是什麼樣子.一旦圖片被成功保存,將會在UIImageView裏面展示出來
4.選擇器消失.
爲了使上面的修改器做用,你將修改ImageSaver ,如今你已經建立了Beer 類,你能夠取消import行和設置圖片路徑行的註釋.打開ImageSaver.m,修改導入語句以下:
- #import "ImageSaver.h"
- #import "Beer.h"
- #import "BeerDetails.h"
如今你須要取消有if語句這行的註釋
- if ([imgData writeToFile:jpgPath atomically:YES]) {
- beer.beerDetails.image = path;
- }
ImageSaver 類已經作好準備來接受圖片了.而且保存圖片到手機的文件目錄裏面.保存路徑到BeerDetails
從這裏開始用戶有兩個選擇,取消或完成,當你建立一個視圖,Beer實體就被建立了,而後插入到managedObjectContext裏面。取消則會刪除Beer 對象。找到cancelAdd,加入以下代碼;
- - (void)cancelAdd {
- [self.beer deleteEntity];
- [self.navigationController popViewControllerAnimated:YES];
- }
MagicalRecord 提供了一個好的方法來刪除實體---從MagicalRecord 裏面移出該實體。刪除以後用戶將返回到beers的主列表。
若是用戶選擇完成,將保存beer 並返回到主列表。找到addNewBeer,它將簡單的pop出view controller,返回到列表。當視圖消失時將調用viewWillDisapper,而後將輪流調用saveContext
如今saveContext 是空的,所以你須要添加代碼來保存新的實體。向saveContext:添加以下代碼:
- - (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堆棧,這將建立一個app全局可用的默認的managedObjectContext 對象。當你建立了 Beer 和BeerDetails 實體,他們就被插入到defaultContext 裏面了。MagicalRecord 容許你保存任何你多是使用saveToPersistentStoreWithCompletion: 的managedObjectContext 。若保存失敗完成的塊裏面講給你一個NSError。這裏你已經添加了一個簡單的if/else塊來打印出保存defaultContext時發生的問題。
你想測試一下結果嗎?繼續運行你的app,選擇+按鈕,填滿內容,選擇完成。
這樣作以後,在列表的頂部你沒有發現新建的Beer,不要急,沒問題,你將學會怎樣調整問題。你可能發現調試器裏面有遺傳信息。與你所說的相反,你成功了!
Magical調試器
當app啓動時,在
Core Data 堆棧啓動期間
MagicalRecord
打印出信息,這說明Core Data 正在啓動。而後建立了defaultContext. 對象。這和咱們前文提到的你保存beer 對象的是同一個defaultContext.
當你用MagicalRecord選擇完成或者保存時,又會出現一系列Log,當你保存時你將看到以下log信息:
一、defaultContext 保存到主線程。
二、任何上下文的父類都將保存,以標誌1設計。
三、最後的log顯示MagicalRecord 知道兩個對象(Beer 和BeerDetail)都將保存,而且被成功保存。
MagicalRecord 爲你打印出了不少log,若是你有問題,或者有些事情的表現出乎你的意料,你應該檢查日誌,來得到有用信息。
注意:
雖然我不推薦這莫作,若是你必定想看到發生什麼狀況當取消掉MagicalRecord 的日誌打印。你能夠在MagicalRecord.h, 的17行吧:
- #define MR_ENABLE_ACTIVE_RECORD_LOGGING 1
改爲
- #define MR_ENABLE_ACTIVE_RECORD_LOGGING 0
Noch ein Bier, bitte(不會翻譯)
若是應用程序值得所作的工做,你將須要看到你所添加的
beers 。打開MasterViewController.m在頂部導入 Beer.h,和 BeerDetails.h
爲了獲得全部保存在
Core Data的Beer,你須要作一些事,viewWillAppear:,裏面,在調用 reloadData.以前添加fetch方法。
- - (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, 加入下列代碼:
- - (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第一次啓動時,建立一個NSUserDefault 來經過評價排序,而且做爲默認創建起來。在這個方法裏面你作以下事情:
一、檢索在NSUserDefault 保存的用來排序的key值。
二、若是排序key是」rating「,上升的變量設爲否,若是是字幕的變量爲是。
三、進行提取
沒錯這裏作的就這莫多。
再來一次,你在使用MagicalRecord 的方法和CoreData交互,findAllSortedBy:ascending 只是用MagicalRecord 執行查找Core Data 實體中衆多方法中的一種,其餘的還有(注意:以後你將用到):
- findAllInContext: –找到上下文提供的全部類型的實體
- findAll – 找到如今線程上下文對象的全部實體
- findAllSortedBy:ascending:inContext: –和以前使用的相似可是限制了提供的上下文對象
- findAllWithPredicate: – 容許你傳遞謂語動詞來搜尋實體。
- findAllSortedBy:ascending:withPredicate:inContext: – 容許傳遞升序標誌來排序,容許一個特別的上下文,還容許傳遞一個謂語動詞來過濾結果集
其實還有許多優勢,----看一下:
NSManagedObject+MagicalFinders.m
.
爲了在單元裏添加beer的名稱和評價,找到configureCell:atIndex:,添加下列代碼:
- - (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,」 添加:
- if ([[segue identifier] isEqualToString:@"editBeer"]) {
- NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
- Beer *beer = self.beers[indexPath.row];
- upcoming.beer = beer;
- }
這將把Beer對象傳遞給
BeerViewController
, 所以就能夠展現beer的詳細信息,容許編輯等。
繼續把你的工程跑起來:
此次你將看到你以前添加的Beer和它的評價,你還能夠選擇Beer而且編輯信息,當你返回時,列表就更新了。
試着查看某一個Beer,不要編輯信息,返回主列表,看一下log信息你將看到:
-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x8b6bfa0) NO CHANGES IN ** DEFAULT ** CONTEXT - NOT SAVING
|
當你離開詳情頁,你在viewWillDisappear:
. 裏面所寫的代碼將保存默認上下文。然而若是沒有變化,
MagicalRecord
識別到沒有必要執行一個保存操做,所以它跳過了執行。這樣作的好處就是,你沒有必要考慮你是否應該保存,只須要嘗試保存,讓 MagicalRecord 給你指出就能夠了。
完成觸摸
這還有一些你想讓app給用戶作的事情,好比刪除Beer,列出你喜好啤酒的列表,執行查詢。
刪除
在 MasterViewController.m,裏面找到tableView:commitEditingStyle:forRowAtIndexPath:, 方法添加以下代碼:
- - (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
.方法,你須要添加一些代碼來確保刪除經過,你已經作過一次了,你能指出怎麼作嗎?準備。。。開始!
添加以下代碼來保存上下文
- // Save ManagedObjectContext using MagicalRecord
- [[NSManagedObjectContext defaultContext] saveToPersistentStoreAndWait];
嚴格來講你不必知道它何時結束,你可使用
MagicalRecord
的其餘方式來保存
managedObjectContext
。
把App跑起來,刪除一個Beer(使用傳統的刪除cell的方式)若是你重啓App,beer就消失了。你作的很對,保存了咱們的更改。這意味着你已經正確的使用了 MagicalRecord。拍拍肩膀,放鬆下。
Demo數據
給用戶一些初始化的數據,用戶就會很容易明白怎麼記錄本身喜歡的啤酒,這樣會更好。在 AppDelegate.m裏面導入 Beer.h, BeerDetails.h. 當創建 Core Data堆棧以後加入如下代碼:
- // 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張灰白色的啤酒照片。在這裏你只須要建立4種不一樣的啤酒,而後保存它們。在
NSUserDefaults
裏面保存個標誌,確保應用裏面預先填好數據模型當應用程序第一次啓動的時候。
再次運行應用程序,如今你就能夠看到全部的新啤酒了。嘗試刪除一個,而後從新運行Ap,而後刪掉的那個就消失了。若是你想再一次看到那幾個啤酒,從設備裏面刪除應用,從新運行應用就能夠了。
搜索
如今你已經有超過一種的啤酒,能夠測試一下搜索的功能,啓動Ap已經包含了一個搜索欄,滑動到列表的頭部就能夠看到。你所須要作的僅僅是添加搜索啤酒的邏輯。
以前你使用過MagicalRecord 的一個方法來獲取全部種類的啤酒。而後她僅僅簡單的返回了全部品種的啤酒,如今你須要在全部啤酒裏面檢索特殊種類的啤酒。
要作到這一點你須要用到謂語動詞。以前教程已經講解了一個使用謂語動詞檢索的方法。----你能猜出來怎麼作嗎?邏輯代碼在MasterViewController.m 的doSearch 方法裏面。
- - (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 有多麼的容易。學會這個樣板真的頗有用。你在教程裏面探索的原理可以幫你開發各類ap,來幫助用戶記錄他們喜歡的圖片,筆記,和評價。多享受啊!
你能夠下載完整的代碼在這個連接,若是你卡在哪裏這將頗有幫助。
若是你想進一步開發這個工程,下面是一些想法:
一、在MasterViewController 裏面添加「還沒建立啤酒」的提示。-----檢查並使用MagicalRecord 裏面的hasAtLeastOneEntity方法。
二、添加消息提示有多少啤酒匹配搜索條件,使用countOfEntitiesWithPredicate: 方法。
三、完善數據庫重置功能-----查看MagicalRecord裏面的truncateAll 方法。
四、若是有興趣打開 MagicalRecordShorthand.h 閱讀如下里面的方法是名稱----大部分方法的名字都很容易理解,這個頭文件應該會給你一些怎麼使用MagicalRecord的一些更好的想法。
若是你對本教程有任何問題,或者有任何評論,請加入下面的討論。
初次翻譯,錯誤之處還請諒解. 完整例子代碼見:
http://download.csdn.net/detail/yjw179/9397366