2014-10-22 14:37 6137人阅读 评论(6) 收藏 举报

目录(?)[+]

刚开始接触IOS不久,尝试着翻译一些博客,积累技术,与大家共享。

本篇内容讲解的是MagicRecord的使用,是对CoreData的深度封装,原文地址:

http://www.raywenderlich.com/56879/magicalrecord-tutorial-ios 欢迎大家指正,谢谢!

CoreData作为Mac OS 和IOS开发数据持久化和用户数据检索的不可缺少的一部分已经好几年了。为了使API对开发者更容易使用,也为了App的整体化,苹果也在不间断的更新CoreData的API。

也就是说,即使对于一个 精通IOS开发的人CoreData依旧使用起来很困难。即使你会使用CoreData,每天重复性枯燥的使用CoreData也会变得很笨 重,MagicalPanda创建的一个第三方库为这种工作带来了好消息。MagicalRecord 致力于更快捷和容易的使用CoreData。

MagicalRecord 使用方便,特别流行。正如作者所说,MagicalRecord 致力于使CoreData的代码更简洁,更简单的获取数据,并且使用最优化的操作。他是怎么做到的呢?它提供了方便的方法,包含了CoreData使用的 查询更新等的公用模板。它的设计受到了Ruby on Rails'sActiveRecord 持续性系统的影响。

但这些理论已经足够了,请跟着这篇教程来见证MagicalRecord怎样应用。在这篇教程里,你将会创建一个app,该App将记录你所喜爱啤酒的一个踪迹。它将允许你做到以下几个事情:

1.添加你所喜爱的一种啤酒。

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文件,该文件是工程的预编译文件,在文件里面增加如下代码:
  1. <span style="font-family:Times New Roman;font-size:14px;">#define MR_SHORTHAND
  2. #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 的方式来添加。
MagicalRecord 项目。
2.拖拽MagicalRecord 目录到你的XCode工程。
CoreData.framework
包被添加进了你的工程设置里面(Build Phases\Link Binary )
#ifdef
__OBJC__代码的下面添加如下代码:
  1. <span style="font-family:Times New Roman;font-size:14px;">#define MR_SHORTHAND
  2. #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
*
CreateNSManagedObjectSubclassCore
Data Model另一个解决方案是让XCode少做一些事,如果你在生成类代码之前已经很明确的在如果你很好奇Xcode怎么从数据模型生成代码,你可以查看Core
Data堆栈了。打开AppDelegate.m文件,在application:didFinishLaunchingWithOptions:方法里面,在return代码前加上下面内容:

  1. // Setup CoreData with MagicalRecord
  2. // Step 1. Setup Core Data Stack with Magical Record
  3. // Step 2. Relax. Why not have a beer? Surely all this talk of beer is making you thirsty…
  4. [MagicalRecord setupCoreDataStackWithStoreNamed:@"BeerModel"];

如果你以前创建过Core Data类型的Xcode工程,你很可能知道在AppDelegate 里面初始化Core
Data需要多少行代码。而使用MagicalRecord你只需要一行代码。

MagicalRecord提供了一些可选的方法来建立你的Core
Data堆栈,可以通过下面的步骤:

1.你的后备存储类型。

2.你是否需要自动迁移。

3.你的Core
Data 模型的名字。

如果你的模型文件和你的工程有一样的基本名称,(比如模型文件的名字是BeerTracker.xcdatamodeld,工程名字是:BeerTracker)

然后你就可以使用MagicalRecord的下列3个方法,setupCoreDataStacksetupCoreDataStackWithInMemoryStore,或者setupAutoMigratingCoreDataStack.

使用名字中有AutoMigrating的方法,你可以改变你的模型,并且可能自动迁移你的存储,MagicalRecord
将帮你操纵这些。通常情况下Core Data则需要你手动添加代码来操作你对模型的一些改变。

调制Beer实体

现在你的Core
Data模型堆栈已经创建起来了,你可以向list里面添加Beer对象了。打开BeerViewController.h文件,在@class
AMRatingControl后面加:

  1. @class Beer;

然后在@interface后面添加一个Beer属性:

  1. @property (nonatomic, strong) Beer *beer;

然后切换到BeerViewController.m,然后在顶部导入 Beer.h 和BeerDetails.h

  1. #import "Beer.h"
  2. #import "BeerDetails.h"

viewDidLoad里面加入以下代码:

  1. - (void)viewDidLoad {
  2. // 1. If there is no beer, create new Beer
  3. if (!self.beer) {
  4. self.beer = [Beer createEntity];
  5. }
  6. // 2. If there are no beer details, create new BeerDetails
  7. if (!self.beer.beerDetails) {
  8. self.beer.beerDetails = [BeerDetails createEntity];
  9. }
  10. // View setup
  11. // 3. Set the title, name, note field and rating of the beer
  12. self.title = self.beer.name ? self.beer.name : @"New Beer";
  13. self.beerNameField.text = self.beer.name;
  14. self.beerNotesView.text = self.beer.beerDetails.note;
  15. self.ratingControl.rating = [self.beer.beerDetails.rating integerValue];
  16. [self.cellOne addSubview:self.ratingControl];
  17. // 4. If there is an image path in the details, show it.
  18. if ([self.beer.beerDetails.image length] > 0) {
  19. // Image setup
  20. NSData *imgData = [NSData dataWithContentsOfFile:[NSHomeDirectory() stringByAppendingPathComponent:self.beer.beerDetails.image]];
  21. [self setImageForBeer:[UIImage imageWithData:imgData]];
  22. }
  23. }

故障检测:如果你把上面的代码贴到你的工程里面报错了,按快捷键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:

  1. - (void)textFieldDidEndEditing:(UITextField *)textField {
  2. if ([textField.text length] > 0) {
  3. self.title = textField.text;
  4. self.beer.name = textField.text;
  5. }
  6. }

现在你将结束添加名字,然后你就可以把beer的名字在文本框内输入为任何内容,只要不空.

为了薄脆笔记内容到 beer的笔记值里面,找到textViewDidEndEditing:方法,向如下编辑

  1. - (void)textViewDidEndEditing:(UITextView *)textView {
  2. [textView resignFirstResponder];
  3. if ([textView.text length] > 0) {
  4. self.beer.beerDetails.note = textView.text;
  5. }
  6. }

下一步确保用户在View Controller里面改变评价,beer的评价会自动更新.在updateRating里面添加:

  1. - (void)updateRating {
  2. self.beer.beerDetails.rating = @(self.ratingControl.rating);
  3. }

当用户在详情页面点击UIImageView,将允许他们添加或者编辑一张图片.一个UIActionSheet 将会展示出来
,它将允许用户下哦那个相机胶卷选择照片,或者拍一张新的照片.如果用户想拍照片,你得确保照片已经保存在磁盘上了.不是吧照片保存在Core Data里面(这将导致性能问题),而是保存在用户的文件目录里面.你只需把图片路径保存在CoreData里面.

通过实现UIImagePickerControllerDelegate 方法,在照片和图库之间管理互动,你需要在UIImagePickerController里面实现BeerViewController 委派,用来在故事板里面操纵视图.找到imagePickerController:didFinishPickingMediaWithinfo,添加如下代码:

  1. - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
  2. // 1. Grab image and save to disk
  3. UIImage *image = info[UIImagePickerControllerOriginalImage];
  4. // 2. Remove old image if present
  5. if (self.beer.beerDetails.image) {
  6. [ImageSaver deleteImageAtPath:self.beer.beerDetails.image];
  7. }
  8. // 3. Save the image
  9. if ([ImageSaver saveImageToDisk:image andToBeer:self.beer]) {
  10. [self setImageForBeer:image];
  11. }
  12. [picker dismissViewControllerAnimated:YES completion:nil];
  13. }

下面讲解下上面的代码:

1.imagePickerController:didFinishPickingMediaWithInfo:间接的传递了用户选择图片的一个参数,,图片是在信息字典里面的,key是UIImagePickerControllerOriginalImage
2.如果Beer图像已经包含了一个图片,程序将把它从硬盘删除.因此你并不会把用户的存储占满.

3.接着新的图片被保存到硬盘,路径被添加到了BeerDetails 的图片属性里面.打开
 ImageSaver 找到saveImageToDisk:andToBeer 看一下
 是什么样子.一旦图片被成功保存,将会在UIImageView里面展现出来

4.选择器消失.

为了使上面的修改器作用,你将修改ImageSaver
,现在你已经创建了Beer 类,你可以取消import行和设置图片路径行的注释.打开ImageSaver.m,修改导入语句如下:

  1. #import "ImageSaver.h"
  2. #import "Beer.h"
  3. #import "BeerDetails.h"

现在你需要取消有if语句这行的注释

  1. if ([imgData writeToFile:jpgPath atomically:YES]) {
  2. beer.beerDetails.image = path;
  3. }

ImageSaver 类已经做好准备来接受图片了.并且保存图片到手机的文件目录里面.保存路径到BeerDetails

从这里开始用户有两个选择,取消或完成,当你创建一个视图,Beer实体就被创建了,然后插入到managedObjectContext里面。取消则会删除Beer
对象。找到cancelAdd,加入如下代码;

  1. - (void)cancelAdd {
  2. [self.beer deleteEntity];
  3. [self.navigationController popViewControllerAnimated:YES];
  4. }

MagicalRecord 提供了一个好的方法来删除实体---从MagicalRecord 里面移出该实体。删除之后用户将返回到beers的主列表。

如果用户选择完成,将保存beer
并返回到主列表。找到addNewBeer,它将简单的pop出view
controller,返回到列表。当视图消失时将调用viewWillDisapper,然后将轮流调用saveContext

saveContext 是空的,因此你需要添加代码来保存新的实体。向saveContext:添加如下代码:

  1. - (void)saveContext {
  2. [[NSManagedObjectContext defaultContext] saveToPersistentStoreWithCompletion:^(BOOL success, NSError *error) {
  3. if (success) {
  4. NSLog(@"You successfully saved your context.");
  5. } else if (error) {
  6. NSLog(@"Error saving context: %@", error.description);
  7. }
  8. }];
  9. }

接下来,还有几行代码要做,在 In AppDelegate.m,
里面用
MagicalRecord建立  Core Data堆栈,这将创建一个app全局可用的默认的managedObjectContext 
对象。当你创建了 Beer 和BeerDetails 实体,他们就被插入到defaultContext 里面了。MagicalRecord 允许你保存任何你可能是使用saveToPersistentStoreWithCompletion:
managedObjectContext 。若保存失败完成的块里面讲给你一个NSError。这里你已经添加了一个简单的if/else块来打印出保存defaultContext时发生的问题。

你想测试一下结果吗?继续运行你的app,选择+按钮,填满内容,选择完成。


这样做之后,在列表的顶部你没有发现新建的Beer,不要急,没问题,你将学会怎样调整问题。你可能发现调试器里面有遗传信息。与你所说的相反,你成功了!

Core Data 堆栈启动期间MagicalRecord 打印出信息,这说明Core
Data 正在启动。然后创建了defaultContext.
对象。这和我们前文提到的你保存beer 对象的是同一个defaultContext.

当你用MagicalRecord选择完成或者保存时,又会出现一系列Log,当你保存时你将看到如下log信息:
1、defaultContext 保存到主线程。
2、任何上下文的父类都将保存,以标志1设计。
3、最后的log显示MagicalRecord 知道两个对象(Beer
和BeerDetail)都将保存,并且被成功保存。
MagicalRecord 为你打印出了很多log,如果你有问题,或者有些事情的表现出乎你的意料,你应该检查日志,来获得有用信息。
注意:
MagicalRecordMagicalRecord.h吧:
  1. #define MR_ENABLE_ACTIVE_RECORD_LOGGING 1
  1. #define MR_ENABLE_ACTIVE_RECORD_LOGGING 0

beers 。打开MasterViewController.m在顶部导入 Beer.h,和 BeerDetails.h

Core Data的Beer,你需要做一些事,viewWillAppear:,里面,在调用 reloadData.之前添加fetch方法。

  1. - (void)viewWillAppear:(BOOL)animated {
  2. [super viewWillAppear:animated];
  3. // Check if the user's sort preference has been saved.
  4. ...
  5. [self fetchAllBeers];
  6. [self.tableView reloadData];
  7. }

当视图第一次加载时,或者从查看或添加beer返回时,将获取和加载所有的beers
到列表中。

找到fetchAllBeers,
加入下列代码:
  1. - (void)fetchAllBeers {
  2. // 1. Get the sort key
  3. NSString *sortKey = [[NSUserDefaults standardUserDefaults] objectForKey:WB_SORT_KEY];
  4. // 2. Determine if it is ascending
  5. BOOL ascending = [sortKey isEqualToString:SORT_KEY_RATING] ? NO : YES;
  6. // 3. Fetch entities with MagicalRecord
  7. self.beers = [[Beer findAllSortedBy:sortKey ascending:ascending] mutableCopy];
  8. }

MasterViewController
允许用户通过评价来排序Beer---从5星到一星,或通过字母排序(A-Z)排序,当App第一次启动时,创建一个NSUserDefault 来通过评价排序,并且作为默认建立起来。在这个方法里面你做如下事情:

1、检索在NSUserDefault 保存的用来排序的key值。
2、如果排序key是”rating“,上升的变量设为否,如果是字幕的变量为是。
3、进行提取
没错这里做的就这莫多。
再来一次,你在使用MagicalRecord 的方法和CoreData交互,findAllSortedBy:ascending 只是用MagicalRecord 执行查找Core
Data 实体中众多方法中的一种,其他的还有(注意:之后你将用到):
  • findAllInContext: –找到上下文提供的所有类型的实体
  • findAll – 找到现在线程上下文对象的所有实体
  • findAllSortedBy:ascending:inContext: –和之前使用的类似但是限制了提供的上下文对象
  • findAllWithPredicate: – 允许你传递谓语动词来搜寻实体。
  • findAllSortedBy:ascending:withPredicate:inContext: –
    允许传递升序标志来排序,允许一个特别的上下文,还允许传递一个谓语动词来过滤结果集

其实还有许多优点,----看一下:NSManagedObject+MagicalFinders.m.

为了在单元里添加beer的名称和评价,找到configureCell:atIndex:,添加下列代码:
  1. - (void)configureCell:(UITableViewCell*)cell atIndex:(NSIndexPath*)indexPath {
  2. // Get current Beer
  3. Beer *beer = self.beers[indexPath.row];
  4. cell.textLabel.text = beer.name;
  5. // Setup AMRatingControl
  6. AMRatingControl *ratingControl;
  7. if (![cell viewWithTag:20]) {
  8. ratingControl = [[AMRatingControl alloc] initWithLocation:CGPointMake(190, 10) emptyImage:[UIImage imageNamed:@"beermug-empty"] solidImage:[UIImage imageNamed:@"beermug-full"] andMaxRating:5];
  9. ratingControl.tag = 20;
  10. ratingControl.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
  11. ratingControl.userInteractionEnabled = NO;
  12. [cell addSubview:ratingControl];
  13. } else {
  14. ratingControl = (AMRatingControl*)[cell viewWithTag:20];
  15. }
  16. // Put beer rating in cell
  17. ratingControl.rating = [beer.beerDetails.rating integerValue];
  18. }

现在,再找到 prepareForSegue:sender:,
在if语句里检查如果segue标识符是“editBeer,” 添加:

  1. if ([[segue identifier] isEqualToString:@"editBeer"]) {
  2. NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
  3. Beer *beer = self.beers[indexPath.row];
  4. upcoming.beer = beer;
  5. }

这将把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:,
方法添加如下代码:

  1. - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
  2. if (editingStyle == UITableViewCellEditingStyleDelete) {
  3. Beer *beerToRemove = self.beers[indexPath.row];
  4. // Remove Image from local documents
  5. if (beerToRemove.beerDetails.image) {
  6. [ImageSaver deleteImageAtPath:beerToRemove.beerDetails.image];
  7. }
  8. // Deleting an Entity with MagicalRecord
  9. [beerToRemove deleteEntity];
  10. [self saveContext];
  11. [self.beers removeObjectAtIndex:indexPath.row];
  12. [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
  13. }
  14. }

记住这里调用了saveContext.方法,你需要添加一些代码来确保删除通过,你已经做过一次了,你能指出怎么做吗?准备。。。开始!

添加如下代码来保存上下文

  1. // Save ManagedObjectContext using MagicalRecord
  2. [[NSManagedObjectContext defaultContext] saveToPersistentStoreAndWait];

严格来说你没必要知道它什么时候结束,你可以使用MagicalRecord
的其他方式来保存managedObjectContext

把App跑起来,删除一个Beer(使用传统的删除cell的方式)如果你重启App,beer就消失了。你做的很对,保存了我们的更改。这意味着你已经正确的使用了 MagicalRecord。拍拍肩膀,放松下。

Demo数据

给用户一些初始化的数据,用户就会很容易明白怎么记录自己喜欢的啤酒,这样会更好。在 AppDelegate.m里面导入 Beer.hBeerDetails.h.
当建立 Core Data堆栈之后加入以下代码:

  1. // Setup App with prefilled Beer items.
  2. if (![[NSUserDefaults standardUserDefaults] objectForKey:@"MR_HasPrefilledBeers"]) {
  3. // Create Blond Ale
  4. Beer *blondAle = [Beer createEntity];
  5. blondAle.name  = @"Blond Ale";
  6. blondAle.beerDetails = [BeerDetails createEntity];
  7. blondAle.beerDetails.rating = @4;
  8. [ImageSaver saveImageToDisk:[UIImage imageNamed:@"blond.jpg"] andToBeer:blondAle];
  9. // Create Wheat Beer
  10. Beer *wheatBeer = [Beer createEntity];
  11. wheatBeer.name  = @"Wheat Beer";
  12. wheatBeer.beerDetails = [BeerDetails createEntity];
  13. wheatBeer.beerDetails.rating = @2;
  14. [ImageSaver saveImageToDisk:[UIImage imageNamed:@"wheat.jpg"] andToBeer:wheatBeer];
  15. // Create Pale Lager
  16. Beer *paleLager = [Beer createEntity];
  17. paleLager.name  = @"Pale Lager";
  18. paleLager.beerDetails = [BeerDetails createEntity];
  19. paleLager.beerDetails.rating = @3;
  20. [ImageSaver saveImageToDisk:[UIImage imageNamed:@"pale.jpg"] andToBeer:paleLager];
  21. // Create Stout
  22. Beer *stout = [Beer createEntity];
  23. stout.name  = @"Stout Lager";
  24. stout.beerDetails = [BeerDetails createEntity];
  25. stout.beerDetails.rating = @5;
  26. [ImageSaver saveImageToDisk:[UIImage imageNamed:@"stout.jpg"] andToBeer:stout];
  27. // Save Managed Object Context
  28. [[NSManagedObjectContext defaultContext] saveToPersistentStoreWithCompletion:nil];
  29. // Set User Default to prevent another preload of data on startup.
  30. [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"MR_HasPrefilledBeers"];
  31. [[NSUserDefaults standardUserDefaults] synchronize];
  32. }

在本教程的开始你下载的启动ap,包含了4张灰白色的啤酒照片。在这里你只需要创建4种不同的啤酒,然后保存它们。在NSUserDefaults 里面保存个标志,确保应用里面预先填好数据模型当应用程序第一次启动的时候。

再次运行应用程序,现在你就可以看到所有的新啤酒了。尝试删除一个,然后重新运行Ap,然后删掉的那个就消失了。如果你想再一次看到那几个啤酒,从设备里面删除应用,重新运行应用就可以了。

搜索

现在你已经有超过一种的啤酒,可以测试一下搜索的功能,启动Ap已经包含了一个搜索栏,滑动到列表的头部就可以看到。你所需要做的仅仅是添加搜索啤酒的逻辑。

之前你使用过MagicalRecord 的一个方法来获取所有种类的啤酒。然后她仅仅简单的返回了所有品种的啤酒,现在你需要在所有啤酒里面检索特殊种类的啤酒。

要做到这一点你需要用到谓语动词。之前教程已经讲解了一个使用谓语动词检索的方法。----你能猜出来怎么做吗?逻辑代码在MasterViewController.m 的doSearch 方法里面。

  1. - (void)doSearch {
  2. // 1. Get the text from the search bar.
  3. NSString *searchText = self.searchBar.text;
  4. // 2. Do a fetch on the beers that match Predicate criteria.
  5. // In this case, if the name contains the string
  6. self.beers = [[Beer findAllSortedBy:SORT_KEY_NAME ascending:YES withPredicate:[NSPredicate predicateWithFormat:@"name contains[c] %@", searchText] inContext:[NSManagedObjectContext defaultContext]] mutableCopy];
  7. // 3. Reload the table to show the query results.
  8. [self.tableView reloadData];
  9. }

再次运行Ap将啤酒列表页面向下拽,一直到出现搜索栏。在列表栏里面搜索(列表里有的和没有的),你得到想要的结果了吗?

从这之后干什么

但愿,MagicalRecord 教程能够展示给你使用MagicalRecord
有多么的容易。学会这个样板真的很有用。你在教程里面探索的原理能够帮你开发各种ap,来帮助用户记录他们喜欢的图片,笔记,和评价。多享受啊!
你可以下载完整的代码在这个链接,如果你卡在哪里这将很有帮助。
如果你想进一步开发这个工程,下面是一些想法:
1、在MasterViewController
里面添加“还没创建啤酒”的提示。-----检查并使用MagicalRecord 里面的hasAtLeastOneEntity方法。
2、添加消息提示有多少啤酒匹配搜索条件,使用countOfEntitiesWithPredicate: 方法。
3、完善数据库重置功能-----查看MagicalRecord里面的truncateAll 方法。
4、如果有兴趣打开 MagicalRecordShorthand.h 阅读以下里面的方法是名称----大部分方法的名字都很容易理解,这个头文件应该会给你一些怎么使用MagicalRecord的一些更好的想法。
如果你对本教程有任何问题,或者有任何评论,请加入下面的讨论。
初次翻译,错误之处还请谅解.  完整例子代码见:

http://download.csdn.net/detail/dongtaochen2039/8139455

 

IOS MagicRecord 详解 (转载)的更多相关文章

  1. 【转】IOS AutoLayout详解(三)用代码实现(附Demo下载)

    转载自:blog.csdn.net/hello_hwc IOS SDK详解 前言: 在开发的过程中,有时候创建View没办法通过Storyboard来进行,又需要AutoLayout,这时候用代码创建 ...

  2. IOS SDK详解

    来源:http://blog.csdn.net/column/details/huangwenchen-ios-sdk.html?page=1#42803301 博客专栏>移动开发专栏>I ...

  3. malloc 与 free函数详解<转载>

    malloc和free函数详解   本文介绍malloc和free函数的内容. 在C中,对内存的管理是相当重要.下面开始介绍这两个函数: 一.malloc()和free()的基本概念以及基本用法: 1 ...

  4. jQuery的deferred对象详解(转载)

    本文转载自: jQuery的deferred对象详解(转载)

  5. Java 反射 设计模式 动态代理机制详解 [ 转载 ]

    Java 反射 设计模式 动态代理机制详解 [ 转载 ] @author 亦山 原文链接:http://blog.csdn.net/luanlouis/article/details/24589193 ...

  6. GridView内容详解(转载)

    GridView内容详解(转载) GridView是ASP.NET界面开发中的一个重要的控件,对GridView使用的熟练程度直接影响软件开发的进度及功能的实现.(车延禄)GridView的主要新特性 ...

  7. 如约而至,Java 10 正式发布! Spring+SpringMVC+MyBatis+easyUI整合进阶篇(十四)Redis缓存正确的使用姿势 努力的孩子运气不会太差,跌宕的人生定当更加精彩 优先队列详解(转载)

    如约而至,Java 10 正式发布!   3 月 20 日,Oracle 宣布 Java 10 正式发布. 官方已提供下载:http://www.oracle.com/technetwork/java ...

  8. Linux下的I/O复用与epoll详解(转载)

    Linux下的I/O复用与epoll详解 转载自:https://www.cnblogs.com/lojunren/p/3856290.html  前言 I/O多路复用有很多种实现.在linux上,2 ...

  9. iOS路由详解

    本文如题,路由详解,注定是一篇详细解释iOS路由原理及使用的文章,由于此时正在外地出差,无法详细一一写出,只能不定时的补充. 一.什么是iOS路由 路由一词来源于路由器,可以实现层级之间消息转发的功能 ...

随机推荐

  1. 10.1(java学习笔记)JDBC基本操作(连接,执行SQL语句,获取结果集)

    一.JDBC JDBC的全称是java database connection java数据库连接. 在java中需要对数据库进行一系列的操作,这时就需要使用JDBC. sun公司制定了关于数据库操作 ...

  2. Problem M: 输出九九乘法表

    #include<stdio.h> int main() { int n,i,j; scanf("%d",&n); n>=&&n<= ...

  3. 动态OSPF配置路由表

    动态ospf设置路由表 以Rourer1为例子 (1)首先设置路由器端口ip Router(config)#inter f0/0 Router(config-if)#ip add 192.168.1. ...

  4. Bootstrap响应式布局

    Bootstrap响应式布局可以使用栅格化系统,其实就是不同的列组合,配合起来便能组合出强大的功能,系统会自动分为最多12列,超出12列会作为一个整体另起一行,像制作表格table的合并列,功能跟co ...

  5. Docker时间和宿主同步

    通过date命令查看时间 查看主机时间 [root@localhost ~]# date 2016年 07月 27日 星期三 22:42:44 CST 查看容器时间 root@b43340ecf5ef ...

  6. Kubernetes dashboard集成heapster

    图形化展示度量指标的实现需要集成k8s的另外一个Addons组件: Heapster . Heapster原生支持K8s(v1.0.6及以后版本)和 CoreOS ,并且支持多种存储后端,比如: In ...

  7. Centos中mount命令挂载windows7共享文件夹

    1)  在ip:10.4.35.77的windows机器上新建用户.这里新建username:myshare,password:myshare123. 选择 [计算机]右键 选择[管理],本地用户和组 ...

  8. 学习ajax总结

    之前公司的ajax学习分享,做一点总结,加深记忆 什么是ajax? 异步的的js和xml,用js异步形式操作xml,工作主要是数据交互 借阅用户操作时间,减少数据请求,可以无刷新请求数据 创建一个对象 ...

  9. 【Android】The application has stopped unexpectedly.Please try again.

    打出的android APK在android4.0.2手机上运行正常,但是在2.3.7的MOTO DEFY ME525上运行失败. android 2.3.3版本的模拟器上面运行失败: Sorry! ...

  10. css - border-radius

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...