CoreData及MagicalRecord学习

本文是对 MagicalRecord github上的翻译

正文:
注意: MagicalRecord 在 ARC 下运作,Core Data 是 ORM 方案,据说带来的麻烦比好处多,且 Core Data 建立的表没有主键,但对于数据库没有性能要求,进行简单的数据操作完全够用,能简化无数的代码量.

In software engineering, the active record pattern is a design pattern found in software that stores its data in relational databases. It was named by Martin Fowler in his book Patterns of Enterprise Application Architecture. The interface to such an object would include functions such as Insert, Update, and Delete, plus properties that correspond more-or-less directly to the columns in the underlying database table.
在软件工程中,对象与数据库中的记录实时映射是一种设计模式,在处理关系型数据库的的软件中多有出现.这种设计模式被记录在 Martin Fowler 的<Patterns of Enterprise Application Architecture> 中.被操作对象的接口应该包含增删改查的方法,基本属性不多不少的刚好与数据库中的一条记录相对应.

Active record is an approach to accessing data in a database. A database table or view is wrapped into a class; thus an object instance is tied to a single row in the table. After creation of an object, a new row is added to the table upon save. Any object loaded gets its information from the database; when an object is updated, the corresponding row in the table is also updated. The wrapper class implements accessor methods or properties for each column in the table or view.
实时映射记录是一种操作数据库的方式,一个数据库的表被封装成一个对象;这个对象中的一个实例会对应着该表中的一条记录.当创建一个对象时,一条记录也被插入到表中并保存起来.任何被加载的对象中的属性信息都从数据库中读取;当一个对象更新时,这个数据库表中对应的记录也会更新.这个被封装的类实现了实时操作的方法,且其属性一一对应于数据库中表的属性.

Wikipedia 维基百科
MagicalRecord was inspired by the ease of Ruby on Rails' Active Record fetching. The goals of this code are:
• Clean up my Core Data related code
• Allow for clear, simple, one-line fetches
• Still allow the modification of the NSFetchRequest when request optimizations are needed
MagicalRecord 灵感来自于简洁的Ruby语言中 Rails' Active Record 查询方式. MagicalRecord 这个开源库的核心思想是:
清除 Core Data 相关的代码
简洁的清除,简单的一行搜索记录的功能
当然允许使用NSFetchRequest,当存在着复杂的搜索条件时

Installing MagicalRecord 安装

Using CocoaPods
One of the easiest ways to integrate MagicalRecord in your project is to use CocoaPods:
Add the following line to your Podfile:
a. Plain
pod "MagicalRecord"
b. With CocoaLumberjack as Logger
pod "MagicalRecord/CocoaLumberjack"
In your project directory, run pod update
You should now be able to add #import <MagicalRecord/MagicalRecord.h> to any of your target's source files and begin using MagicalRecord!
最简单的融入MagicalRecord到你的工程的一个方法是使用CocoaPods
添加以下的标示到你的Podfile文件
a.简单的
pod "MagicalRecord"
b.用CocoaLumberjack记录器
pod "MagicalRecord/CocoaLumberjack"
在你的项目目录中,运行更新仓
你现在应该可以添加#import < MagicalRecord / MagicalRecord.h >到任何源文件并开始使用MagicalRecord !

**Shorthand Category Methods **速记分类方法

By default, all of the category methods that MagicalRecord provides are prefixed with MR_. This is inline with Apple's recommendation not to create unadorned category methods to avoid naming clashes.
If you like, you can include the following headers to use shorter, non-prefixed category methods:
默认情况下,所有的MR_ MagicalRecord提供的类方法是以MR_为前缀。这是(内联与)根据苹果的建议而不是创建不加装饰的分类方法来避免命名冲突。
如果你喜欢,你可以包括下列使用短的标题,没有前缀的分类方法:

#import <MagicalRecord/MagicalRecord.h>
#import <MagicalRecord/MagicalRecord+ShorthandMethods.h>
#import <MagicalRecord/MagicalRecordShorthandMethodAliases.h>

If you're using Swift, you'll need to add these imports to your target's Objective-C bridging header.
Once you've included the headers, you should call the +[MagicalRecord enableShorthandMethods] class method before you setup/use MagicalRecord:
如果你使用Swift、你需要添加这些入口到你的目标的objective - c桥接头文件。
一旦你包括标题,在你设置/使用MagicalRecord:之前你应该唤起+[MagicalRecord enableShorthandMethods]类方法

  • (void)theMethodWhereYouSetupMagicalRecord
    {
    [MagicalRecord enableShorthandMethods];
    // Setup MagicalRecord as per usual 设置MagicalRecord按往常一样
    }
**Please note that we do not offer support for this feature**. If it doesn't work, [please file an issue](https://github.com/magicalpanda/MagicalRecord/issues/new) and we'll fix it when we can.
请注意,我们不支持这个功能。如果它不工作,请文件描述问题,当我们可能的时候我们会解决它。

- [Getting Started](https://github.com/magicalpanda/MagicalRecord/blob/master/Docs/Getting-Started.md)

>To get started, import the MagicalRecord.h header file in your project's pch file. This will allow a global include of all the required headers.
首先,导入MagicalRecord.h头文件在您的项目的pch文件。这将允许全局包括所有需要的头文件。
If you're using CocoaPods or MagicalRecord.framework, your import should look like:
如果你使用CocoaPods或MagicalRecord框架,你的导入应该看起来像:

// Objective-C

import <MagicalRecord/MagicalRecord.h>

// Swift
import MagicalRecord

Otherwise, if you've added MagicalRecord's source files directly to your Objective-C project, your import should be:    
否则,如果你已经直接地添加MagicalRecord的源文件到你的 objective - c项目中,你的导入应该是:
    #import "MagicalRecord.h"
Next, somewhere in your app delegate, in either the - applicationDidFinishLaunching: withOptions: method, or -awakeFromNib, use one of the following setup calls with the MagicalRecord class:
接下来,在您的应用程序委托的一些地方,无论是- applicationDidFinishLaunching:withOptions:方法,或-awakefromnib,使用以下设置的一个调用MagicalRecord类:
  • (void)setupCoreDataStack;
  • (void)setupAutoMigratingCoreDataStack;
  • (void)setupCoreDataStackWithInMemoryStore;
  • (void)setupCoreDataStackWithStoreNamed:(NSString *)storeName;
  • (void)setupCoreDataStackWithAutoMigratingSqliteStoreNamed:(NSString *)storeName;
  • (void)setupCoreDataStackWithStoreAtURL:(NSURL *)storeURL;
  • (void)setupCoreDataStackWithAutoMigratingSqliteStoreAtURL:(NSURL *)storeURL;
Each call instantiates one of each piece of the Core Data stack, and provides getter and setter methods for these instances. These well known instances to MagicalRecord, and are recognized as "defaults".
每次调用所有实例化各个核心数据栈之一,并为这些实例提供了getter和setter方法。这些众所周知的实例MagicalRecord,被认为是“默认的”。
When using the default SQLite data store with the DEBUG flag set, changing your model without creating a new model version will cause MagicalRecord to delete the old store and create a new one automatically. This can be a huge time saver — no more needing to uninstall and reinstall your app every time you make a change your data model! Please be sure not to ship your app with DEBUG enabled: Deleting your app's data without telling the user about it is really bad form!
当使用默认SQLite数据存储用DEBUG调试标记设置,改变你的模型没有创建一个新的模型版本的时候将导致MagicalRecord删除旧的存储和自动创建一个新的。这可以节省大量时间,每次你改变你的数据模型就不再需要卸载和重新安装应用程序。请确保不要将你的应用程序与调试功能连接:删除应用程序的数据而没有告诉用户它是非常糟糕的!
Before your app exits, you should call +cleanUp class method:
在程序退出之前,你应该调用+ cleanUp清理类方法:

[MagicalRecord cleanUp];

This tidies up after MagicalRecord, tearing down our custom error handling and setting all of the Core Data stack created by MagicalRecord to nil.      
这要收拾在MagicalRecord后,拆除我们的自定义错误处理和设置所有的由MagicalRecord创建的核心数据堆栈为零。

>**iCloud-enabled Persistent Stores iCloud功能的持久存储**
To take advantage of Apple's iCloud Core Data syncing, use one of the following setup methods in place of the standard methods listed in the previous section:  
利用苹果的iCloud核心数据同步,使用以下设置方法之一 代替 在前一节中列出的标准方法:
>```
>+ (void)setupCoreDataStackWithiCloudContainer:(NSString *)containerID
                              localStoreNamed:(NSString *)localStore;

>+ (void)setupCoreDataStackWithiCloudContainer:(NSString *)containerID
                               contentNameKey:(NSString *)contentNameKey
                              localStoreNamed:(NSString *)localStoreName
                      cloudStorePathComponent:(NSString *)pathSubcomponent;

>+ (void)setupCoreDataStackWithiCloudContainer:(NSString *)containerID
                               contentNameKey:(NSString *)contentNameKey
                              localStoreNamed:(NSString *)localStoreName
                      cloudStorePathComponent:(NSString *)pathSubcomponent
                                   completion:(void (^)(void))completion;

>+ (void)setupCoreDataStackWithiCloudContainer:(NSString *)containerID
                              localStoreAtURL:(NSURL *)storeURL;

>+ (void)setupCoreDataStackWithiCloudContainer:(NSString *)containerID
                               contentNameKey:(NSString *)contentNameKey
                              localStoreAtURL:(NSURL *)storeURL
                      cloudStorePathComponent:(NSString *)pathSubcomponent;

>+ (void)setupCoreDataStackWithiCloudContainer:(NSString *)containerID
                               contentNameKey:(NSString *)contentNameKey
                              localStoreAtURL:(NSURL *)storeURL
                      cloudStorePathComponent:(NSString *)pathSubcomponent
                                   completion:(void (^)(void))completion;
>```

>For further details, please refer to [Apple's "iCloud Programming Guide for Core Data"](https://developer.apple.com/library/ios/documentation/DataManagement/Conceptual/UsingCoreDataWithiCloudPG/Introduction/Introduction.html#//apple_ref/doc/uid/TP40013491). 
要了解进一步的细节,请参阅苹果的iCloud编程指南的核心数据。

>**Notes**
If you are managing multiple iCloud-enabled stores, we recommended that you use one of the longer setup methods that allows you to specify your own contentNameKey. The shorter setup methods automatically generate theNSPersistentStoreUbiquitousContentNameKey based on your app's bundle identifier (CFBundleIdentifier):
如果您管理多个iCloud-enabled商店,我们建议您使用一个较长的设置方法,允许您指定自己的contentNameKey。较短的设置方法自动生成基于应用程序的包标识符(CFBundleIdentifier):的NSPersistentStoreUbiquitousContentNameKey

- [Working with Managed Object Contexts](https://github.com/magicalpanda/MagicalRecord/blob/master/Docs/Working-with-Managed-Object-Contexts.md)

>**Working with Managed Object Contexts  工作与管理对象上下文**

>**Creating New Contexts 创建新环境**
A variety of simple class methods are provided to help you create new contexts:  
提供各种简单的类方法来帮助您创建新的上下文:
- **+[NSManagedObjectContext MR_newContext]**: Sets the default context as it's parent context. Has a concurrency type of NSPrivateQueueConcurrencyType.
设置默认上下文作为它的父上下文。有一个并发的NSPrivateQueueConcurrencyType类型。
- **+[NSManagedObjectContext MR_newMainQueueContext]**: Has a concurrency type of NSMainQueueConcurrencyType.
一种并发NSMainQueueConcurrencyType类型。
- **+[NSManagedObjectContext MR_newPrivateQueueContext]**: Has a concurrency type of NSPrivateQueueConcurrencyType.
一种并发NSPrivateQueueConcurrencyType 类型。
- **+[NSManagedObjectContext MR_newContextWithParent:…]**: Allows you to specify the parent context that will be set. Has a concurrency type of NSPrivateQueueConcurrencyType.
允许您指定将被设置的父上下文。有一个并发的NSPrivateQueueConcurrencyType类型。
- **+[NSManagedObjectContext MR_newContextWithStoreCoordinator:…]**: Allows you to specify the persistent store coordinator for the new context. Has a concurrency type of NSPrivateQueueConcurrencyType.
允许您指定持久性存储协调员作为新的上下文。有一个并发的NSPrivateQueueConcurrencyType类型。

>**The Default Context  默认的上下文**
When working with Core Data, you will regularly deal with two main objects: NSManagedObject and NSManagedObjectContext. 
使用Core Data时,您将定期处理两个主要对象:NSManagedObject NSManagedObjectContext。
MagicalRecord provides a simple class method to retrieve a default NSManagedObjectContext that can be used throughout your app. This context operates on the main thread, and is great for simple, single-threaded apps.        
MagicalRecord提供了一个简单的类方法来检索一个默认的可以始终在你的App使用的NSManagedObjectContext,。这种上下文运行在主线程,且十分的简单,单线程应用在程序中。
To access the default context, call:   访问默认上下文,使用:

NSManagedObjectContext *defaultContext = [NSManagedObjectContext MR_defaultContext];

This context will be used throughout MagicalRecord in any method that uses a context, but does not provde a specific managed object context parameter.  
在使用一个上下文的任何方法里,这种上下文将贯穿整个MagicalRecord使用,但并不能验证特定管理对象上下文参数。
If you need to create a new managed object context for use in non-main threads, use the following method:   
如果您需要创建一个新的管理对象上下文用于非主线程,使用下面的方法:

NSManagedObjectContext *myNewContext = [NSManagedObjectContext MR_newContext];

This will create a new managed object context which has the same object model and persistent store as the default context, but is safe for use on another thread. It automatically sets the default context as it's parent context. 
这将会创建一个新的管理对象上下文,它有相同的对象模型和持久化存储作为默认上下文,但是是安全的使用在另一个线程上。它会自动设置默认上下文作为父上下文。
If you'd like to make your myNewContext instance the default for all fetch requests, use the following class method:    
如果你想让你的myNewContext实例默认的为所有获取请求,使用以下类方法:

[NSManagedObjectContext MR_setDefaultContext:myNewContext];

**NOTE**: It is highly recommended that the default context is created and set on the main thread using a managed object context with a concurrency type of NSMainQueueConcurrencyType.
注意:强烈建议默认上下文被创建且使用管理对象上下文设置在主线程用并发NSMainQueueConcurrencyType类型。

>**Performing Work on Background Threads        在后台线程执行工作**
MagicalRecord provides methods to set up and work with contexts for use in background threads. The background saving operations are inspired by the UIView animation block methods, with a few minor differences:   
MagicalRecord提供方法来设置和使用上下文在后台线程中使用。后台操作受UIView动画块方法,有一些细微的差别:
•  The block in which you make changes to your entities will never be executed on the main thread.  
你改变实体的块永远不会在主线程上执行。
•  A single NSManagedObjectContext is provided for you within these blocks. 
单个NSManagedObjectContext为你提供在这些街区。
For example, if we have Person entity, and we need to set the firstName and lastName fields, this is how you would use MagicalRecord to setup a background context for your use:
例如,如果我们有实体的人,我们需要设置firstName和lastName字段,这是如何使用MagicalRecord设置背景为您的使用环境:
>```
>Person *person = ...;

>[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext)>{

  >Person *localPerson = [person MR_inContext:localContext];
  >localPerson.firstName = @"John";
 > localPerson.lastName = @"Appleseed";

>}];
>```
In this method, the specified block provides you with the proper context in which to perform your operations, you don't need to worry about setting up the context so that it tells the Default Context that it's done, and should update because changes were performed on another thread.
在这种方法中,指定的块为您提供适当的上下文来执行您的操作,你不需要担心设置上下文,以便它告诉默认上下文,就完成了,而且应该更新,因为修改另一个线程上执行。
To perform an action after this save block is completed, you can fill in a completion block:
块后执行一个动作完成后,你可以填写完成块:
>```
>Person *person = ...;

>[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext)>{

  >Person *localPerson = [person MR_inContext:localContext];
  >localPerson.firstName = @"John";
  >localPerson.lastName = @"Appleseed";

>} completion:^(BOOL success, NSError *error) {

  >self.everyoneInTheDepartment = [Person findAll];

>}];

>```
This completion block is called on the main thread (queue), so this is also safe for triggering UI updates.
这个完成块呼吁主线程(队列),所以这也是安全的触发UI更新。

- [Creating Entities](https://github.com/magicalpanda/MagicalRecord/blob/master/Docs/Creating-Entities.md)

>**Creating Entities  创建实体**
To create and insert a new instance of an Entity in the default context, you can use:  
创建和插入一个新实例的实体在缺省情况下,您可以使用:

Person *myPerson = [Person MR_createEntity];```
To create and insert an entity into specific context:
创建和插入一个实体特定上下文:

Person *myPerson = [Person MR_createEntityInContext:otherContext];```

- [Deleting Entities](https://github.com/magicalpanda/MagicalRecord/blob/master/Docs/Deleting-Entities.md)

>**Deleting Entities  删除实体**
To delete a single entity in the default context: 
删除一个单一的实体在默认上下文:

[myPerson MR_deleteEntity];```
To delete the entity from a specific context:
删除实体从一个特定的背景:

[myPerson MR_deleteEntityInContext:otherContext];```
To truncate all entities from the default context:  
从默认的上下文截断所有实体:

[Person MR_truncateAll];```
To truncate all entities in a specific context:
截断所有实体在一个特定的背景:

[Person MR_truncateAllInContext:otherContext];```

- [Fetching Entities](https://github.com/magicalpanda/MagicalRecord/blob/master/Docs/Fetching-Entities.md)

>###**Fetching Entities     获取实体**

>**Basic Finding    基本的发现**
Most methods in MagicalRecord return an NSArray of results. 
大多数方法MagicalRecord NSArray返回的结果。
As an example, if you have an entity named *Person* related to a *Department* entity (as seen in many of [Apple's Core Data examples](https://github.com/magicalpanda/MagicalRecord/blob/master/Docs/.com/library/mac/documentation/Cocoa/Conceptual/CoreData/Articles/cdBasics.html#/apple_ref/doc/uid/TP40001650-TP1)), you can retrieve all of the *Person* entities from your persistent store using the following method: 
作为一个例子,如果你有一个Person实体相关部门实体(正如在很多苹果的核心数据的例子),你可以从持久存储中检索所有人的实体使用以下方法:

NSArray *people = [Person MR_findAll];```
To return the same entities sorted by a specific attribute:
返回相同的实体按特定的属性:

NSArray *peopleSorted = [Person MR_findAllSortedBy:@"LastName"
                                         ascending:YES];```
To return the entities sorted by multiple attributes:       
返回的实体排序由多个属性:

NSArray *peopleSorted = [Person MR_findAllSortedBy:@"LastName,FirstName"
ascending:YES];```
To return the results sorted by multiple attributes with different values. If you don't provide a value for any attribute, it will default to whatever you've set in your model:
返回结果按多个属性具有不同的值。如果你不为任何属性提供一个值,它将默认为你已经在你的模型:

NSArray *peopleSorted = [Person MR_findAllSortedBy:@"LastName:NO,FirstName"
                                     ascending:YES];

// OR

NSArray *peopleSorted = [Person MR_findAllSortedBy:@"LastName,FirstName:YES"
ascending:NO];```
If you have a unique way of retrieving a single object from your data store (such as an identifier attribute), you can use the following method:
如果你有一个独特的检索方式从数据存储一个对象(比如一个标识符属性),您可以使用以下方法:

Person *person = [Person MR_findFirstByAttribute:@"FirstName"
                                       withValue:@"Forrest"];```

>**Advanced Finding 先进的发现**
If you want to be more specific with your search, you can use a predicate:  
如果你想要更具体的和你的搜索,你可以使用一个谓词:

NSPredicate *peopleFilter = [NSPredicate predicateWithFormat:@"Department IN %@", @[dept1, dept2]];
NSArray *people = [Person MR_findAllWithPredicate:peopleFilter];```

Returning an NSFetchRequest 返回一个NSFetchRequest

NSPredicate *peopleFilter = [NSPredicate predicateWithFormat:@"Department IN %@", departments];
NSFetchRequest *people = [Person MR_requestAllWithPredicate:peopleFilter];```
For each of these single line calls, an NSFetchRequest and NSSortDescriptors for any sorting criteria are created.  
每个一行调用,一个NSFetchRequest NSSortDescriptors创建的任何分类标准。

>**Customizing the Request  自定义请求**
>```
>NSPredicate *peopleFilter = [NSPredicate predicateWithFormat:@"Department IN %@", departments];

>NSFetchRequest *peopleRequest = [Person MR_requestAllWithPredicate:peopleFilter];
>[peopleRequest setReturnsDistinctResults:NO];
>[peopleRequest setReturnPropertiesNamed:@[@"FirstName", @"LastName"]];

>NSArray *people = [Person MR_executeFetchRequest:peopleRequest];```

>**Find the number of entities  找到实体的数量**
You can also perform a count of all entities of a specific type in your persistent store:   
您还可以执行特定类型的所有实体的计算你的持久性存储:

NSNumber *count = [Person MR_numberOfEntities];```
Or, if you're looking for a count of entities based on a predicate or some filter:
或者,如果你正在寻找一个计数的实体基于谓词或一些过滤器:

NSNumber *count = [Person MR_numberOfEntitiesWithPredicate:...];```
There are also complementary methods which return NSUInteger rather than NSNumber instances:        
也有互补的方法,返回了NSUInteger而不是NSNumber实例:
  • (NSUInteger) MR_countOfEntities;
  • (NSUInteger) MR_countOfEntitiesWithContext:(NSManagedObjectContext *)context;
  • (NSUInteger) MR_countOfEntitiesWithPredicate:(NSPredicate *)searchFilter;
  • (NSUInteger) MR_countOfEntitiesWithPredicate:(NSPredicate *)searchFilter
    inContext:(NSManagedObjectContext *)context;

>**Aggregate Operations 聚合操作**
>```
>NSNumber *totalCalories = [CTFoodDiaryEntry MR_aggregateOperation:@"sum:"
                                                      onAttribute:@"calories"
                                                    withPredicate:predicate];

>NSNumber *mostCalories  = [CTFoodDiaryEntry MR_aggregateOperation:@"max:"
                                                      onAttribute:@"calories"
                                                    withPredicate:predicate];

>NSArray *caloriesByMonth = [CTFoodDiaryEntry MR_aggregateOperation:@"sum:"
                                                       onAttribute:@"calories"
                                                     withPredicate:predicate
                                                           groupBy:@"month"];
>```

>**Finding entities in a specific context   发现实体在一个特定的上下文**
All find, fetch, and request methods have an inContext: method parameter that allows you to specify which managed object context you'd like to query:   
所有发现,取回,并要求有它的方法:方法参数,允许您指定管理对象上下文你想查询:
>```
>NSArray *peopleFromAnotherContext = [Person MR_findAllInContext:someOtherContext];

>Person *personFromContext = [Person MR_findFirstByAttribute:@"lastName"
                                                  withValue:@"Gump"
                                                  inContext:someOtherContext];

>NSUInteger count = [Person MR_numberOfEntitiesWithContext:someOtherContext];

Saving Entities 保存实体

When should I save? 当我要保存吗?
In general, your app should save to it's persistent store(s) when data changes. Some applications choose to save on application termination, however this shouldn't be necessary in most circumstances — in fact, if you're only saving when your app terminates, you're risking data loss! What happens if your app crashes? The user will lose all the changes they've made — that's a terrible experience, and easily avoided.
一般来说,应用程序应该保存到它的持久性存储(s)当数据更改的时候。一些应用程序选择节省应用程序终止,然而这个应该是不必要的在大多数情况下——事实上,如果你只保存应用程序终止时,你面临着丢失数据!如果你的应用程序崩溃,会发生什么?用户将失去他们的所有更改,这是一个可怕的经历,且容易避免。
If you find that saving is taking a long time, there are a couple of things you should consider doing:
如果你发现保存很长一段时间,有几件事情你应该考虑做:
1 . Save in a background thread: MagicalRecord provides a simple, clean API for making changes to your entities and subsequently saving them in a background thread — for example:
保存在一个后台线程:MagicalRecord提供了一个简单,干净的API更改你的实体和随后保存在一个后台线程,例如:

[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
        >// Do your work to be saved here, against the `localContext` instance
       > // Everything you do in this block will occur on a background thread
    
    >} completion:^(BOOL success, NSError *error) {
            [application endBackgroundTask:bgTask];
            bgTask = UIBackgroundTaskInvalid;
    >}];```

2 . Break the task down into smaller saves: tasks like importing large amounts of data should always be broken down into smaller chunks. There's no one-size-fits all rule for how much data you should be saving in one go, so you'll need to measure your application's performance using a tool like Apple's Instruments and tune appropriately.

把任务分解成较小的保存:任务导入大量数据应该被分解成小块。没有统一的规则你应该节约多少数据,所以你需要测量应用程序的性能使用像苹果这样的工具的工具和适当调整。

Handling Long-running Saves 处理长期保存

On iOS 在iOS
When an application terminates on iOS, it is given a small window of opportunity to tidy up and save any data to disk. If you know that a save operation is likely to take a while, the best approach is to request an extension to your application's expiration, like so:
iOS应用程序终止时,它给出一个小机会整理并保存任何数据到磁盘。如果你知道一个保存操作可能需要一段时间,最好的方法是请求的扩展应用程序的过期,像这样:

UIApplication *application = [UIApplication sharedApplication];

__block UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];

[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {

>// Do your work to be saved here

} completion:^(BOOL success, NSError *error) {
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];

Be sure to carefully [read the documentation for beginBackgroundTaskWithExpirationHandler
](https://developer.apple.com/library/iOS/documentation/UIKit/Reference/UIApplication_Class/Reference/Reference.html#//apple_ref/occ/instm/UIApplication/beginBackgroundTaskWithExpirationHandler:), as inappropriately or unnecessarily extending your application's lifetime may earn your app a rejection from the App Store.  
beginBackgroundTaskWithExpirationHandler一定要仔细阅读文档,不当或不必要的扩展应用程序的生命周期可能会赢得你的应用程序从应用程序商店拒绝。

>**On OS X  在OS X**
On OS X Mavericks (10.9) and later, App Nap can cause your application to act as though it is effectively terminated when it is in the background. If you know that a save operation is likely to take a while, the best approach is to disable automatic and sudden termination temporarily (assuming that your app supports these features):  
在OS X小牛(10.9)和后,应用午睡会使您的应用程序充当虽然有效地终止时的背景。如果你知道一个保存操作可能需要一段时间,最好的方法是暂时禁用自动和突然终止(假设您的应用程序支持这些特性):
>```
>NSProcessInfo *processInfo = [NSProcessInfo processInfo];

>[processInfo disableSuddenTermination];
>[processInfo disableAutomaticTermination:@"Application is currently saving to persistent store"];

>[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {

    >// Do your work to be saved here

>} completion:^(BOOL success, NSError *error) {
    [processInfo enableSuddenTermination];
    [processInfo enableAutomaticTermination:@"Application has finished saving to the persistent store"];
>}];

As with the iOS approach, be sure to read the documentation on NSProcessInfo before implementing this approach in your app.
与iOS的方法,一定要阅读文档在NSProcessInfo实施这种方法在你的应用程序。

Changes to saving in MagicalRecord 2.3.0 变化在MagicalRecord tripwire储蓄

Context For Current Thread Deprecation 当前线程上下文弃用
In earlier releases of MagicalRecord, we provided methods to retrieve the managed object context for the thread that the method was called on. Unfortunately, it's not possible to return the context for the currently executing thread in a reliable manner anymore. Grand Central Dispatch (GCD) makes no guarantees that a queue will be executed on a single thread, and our approach was based upon the older NSThread API while CoreData has transitioned to use GCD. For more details, please see Saul's post "Why contextForCurrentThread Doesn't Work in MagicalRecord".
MagicalRecord的早期版本中,我们提供了方法来检索管理对象上下文的线程的方法被称为。不幸的是,它是不可能返回当前执行的线程的上下文以可靠的方式了。中央调度(GCD)毫无保证队列将单个线程上执行,和我们的方法是基于老NSThread API虽然CoreData转换到使用肾小球囊性肾病。有关详细信息,请参阅扫罗的文章“为什么MagicalRecord contextForCurrentThread行不通”。
In MagicalRecord 2.3.0, we continue to use +MR_contextForCurrentThread internally in a few places to maintain compatibility with older releases. These methods are deprecated, and you will be warned if you use them.
在MagicalRecord tripwire,我们继续使用+ MR_contextForCurrentThread内部在一些地方保持兼容老版本。这些方法被弃用,你会警告说如果你使用它们。
In particular, do not use +MR_contextForCurrentThread from within any of the +[MagicalRecord saveWithBlock:…] methods — the returned context may not be correct!
特别是,不使用+从内部MR_contextForCurrentThread任何+[MagicalRecord saveWithBlock:…]方法——返回上下文可能不是正确的!
If you'd like to begin preparing for the change now, please use the method variants that accept a "context" parameter, and use the context that's passed to you in the +[MagicalRecord saveWithBlock:…] method block. Instead of:
如果你想开始准备改变现在,请使用方法的变体,接受“上下文”参数,并使用上下文传递给你的+(MagicalRecord saveWithBlock:…)方法。而不是:

[MagicalRecord saveWithBlockAndWait:^(NSManagedObjectContext *localContext) {
    NSManagedObject *inserted = [SingleEntityWithNoRelationships MR_createEntity];
    // …
}];

You should now use:
现在,您应该使用:

[MagicalRecord saveWithBlockAndWait:^(NSManagedObjectContext *localContext) {
    NSManagedObject *inserted = [SingleEntityWithNoRelationships MR_createEntityInContext:localContext];
    // …
}];

When MagicalRecord 3.0 is released, the context for current thread methods will be removed entirely. The methods that do not accept a "context" parameter will move to using the default context of the default stack — please see the MagicalRecord 3.0 release notes for more details.
MagicalRecord 3.0发布时,当前线程的上下文方法完全将被删除。方法,不接受“上下文”参数将使用默认上下文默认的堆栈-请参阅MagicalRecord 3.0发行说明了解更多细节。

Changes to saving in MagicalRecord 2.2.0 改变在MagicalRecord 2.2.0储蓄
In MagicalRecord 2.2, the APIs for saving were revised to behave more consistently, and also to follow naming patterns present in Core Data. Extensive work has gone into adding automated tests that ensure the save methods (both new and deprecated) continue to work as expected through future updates.
在MagicalRecord 2.2中,储蓄的api是修改后的表现更加一致,并遵循命名模式出现在核心数据。广泛的工作已经进入添加自动化测试,确保保存方法(新和弃用)继续工作如预期在未来的更新。
MR_save has been temporarily restored to it's original state of running synchronously on the current thread, and saving to the persistent store. However, the MR_save method is marked as deprecated and will be removed in the next major release of MagicalRecord (version 3.0). You should use MR_saveToPersistentStoreAndWait if you want the same behaviour in future versions of the library.
MR_save已经暂时恢复到原始状态的运行在当前线程同步,并保存到持久性存储。然而,MR_save方法标记为过时的,将被删除的下一个主要版本MagicalRecord(版本3.0)。您应该使用MR_saveToPersistentStoreAndWait如果你想同样的行为在未来版本的库。

New Methods 新方法
The following methods have been added: 添加了以下方法:
NSManagedObjectContext+MagicalSaves

• - (void) MR_saveOnlySelfWithCompletion:(MRSaveCompletionHandler)completion;
• - (void) MR_saveToPersistentStoreWithCompletion:(MRSaveCompletionHandler)completion;
• - (void) MR_saveOnlySelfAndWait;
• - (void) MR_saveToPersistentStoreAndWait;
• - (void) MR_saveWithOptions:(MRSaveContextOptions)mask completion:(MRSaveCompletionHandler)completion;

MagicalRecord+Actions

• + (void) saveWithBlock:(void(^)(NSManagedObjectContext *localContext))block;
• + (void) saveWithBlock:(void(^)(NSManagedObjectContext *localContext))block completion:(MRSaveCompletionHandler)completion;
• + (void) saveWithBlockAndWait:(void(^)(NSManagedObjectContext *localContext))block;
• + (void) saveUsingCurrentThreadContextWithBlock:(void (^)(NSManagedObjectContext *localContext))block completion:(MRSaveCompletionHandler)completion;
• + (void) saveUsingCurrentThreadContextWithBlockAndWait:(void (^)(NSManagedObjectContext *localContext))block;

Deprecations 的用法
The following methods have been deprecated in favour of newer alternatives, and will be removed in MagicalRecord 3.0:
下列方法已被弃用的新选择,和将被删除在MagicalRecord 3.0:
NSManagedObjectContext+MagicalSaves

• - (void) MR_save;
• - (void) MR_saveWithErrorCallback:(void(^)(NSError *error))errorCallback;
• - (void) MR_saveInBackgroundCompletion:(void (^)(void))completion;
• - (void) MR_saveInBackgroundErrorHandler:(void (^)(NSError *error))errorCallback;
• - (void) MR_saveInBackgroundErrorHandler:(void (^)(NSError *error))errorCallback completion:(void (^)(void))completion;
• - (void) MR_saveNestedContexts;
• - (void) MR_saveNestedContextsErrorHandler:(void (^)(NSError *error))errorCallback;
• - (void) MR_saveNestedContextsErrorHandler:(void (^)(NSError *error))errorCallback completion:(void (^)(void))completion;

MagicalRecord+Actions

• + (void) saveWithBlock:(void(^)(NSManagedObjectContext *localContext))block;
• + (void) saveInBackgroundWithBlock:(void(^)(NSManagedObjectContext *localContext))block;
• + (void) saveInBackgroundWithBlock:(void(^)(NSManagedObjectContext *localContext))block completion:(void(^)(void))completion;
• + (void) saveInBackgroundUsingCurrentContextWithBlock:(void (^)(NSManagedObjectContext *localContext))block completion:(void (^)(void))completion errorHandler:(void (^)(NSError *error))errorHandler;

Importing Data 导入数据
We're working on updating this documentation — thanks for your patience. For the moment, please refer to Importing Data Made Easy at Cocoa Is My Girlfriend. Much of this document is based upon Saul's work in that original article.
我们正在更新这个文档,谢谢你的耐心。目前,请参考导入数据很容易在可可是我的女朋友。本文基于扫罗的工作在原来的文章。
MagicalRecord Team
MagicalRecord团队
MagicalRecord can help import data from standard NSObject instances such as NSArray and NSDictionary directly into your Core Data store.
MagicalRecord可以帮助导入数据从标准如NSArray和NSDictionary NSObject实例直接进入你的核心数据存储。
It's a two step process to import data from an external source into your persistent store using MagicalRecord:
这是一个两步的过程,从外部源数据导入到持久性存储使用MagicalRecord:

  1. Define how the data you're importing maps to your store using your data model (it's pretty much codeless!)
    定义如何将数据导入映射到你的商店使用您的数据模型(几乎无代码!)
  2. Perform the data import
    执行数据导入

Define Your Import 定义您的进口
Data from external sources can be wildly variable in quality and structure, so we've done our best to make MagicalRecord's import processes flexible.
从外部数据源的数据可以广泛的变量在质量和结构,所以我们已经尽力使MagicalRecord的进口流程灵活。

MagicalRecord can import data from any Key-Value Coding (KVC) compliant object. We usually find people work withNSArray and NSDictionary instances, but it works just fine with any KVC compliant NSObject subclass.
MagicalRecord可以导入数据从任何键值编码(现有的)兼容的对象。我们通常发现人们使用NSArray和NSDictionary实例,但它工作得很好与任何现有的兼容NSObject子类。
MagicalRecord makes use of the Xcode data modeling tool's "User Info" values to allow configuration of import options and mappings possible without having to edit any code.
MagicalRecord使用Xcode数据建模工具的“用户信息”值允许进口的配置选项和映射可能不需要修改任何代码。

Paste_Image.png

For reference: The user info keys and values are held in an NSDictionary that is attached to every entity, attribute and relationship in your data model, and can be accessed via the userInfo method on your NSEntityDescriptioninstances.
供参考:用户信息键和值在NSDictionary附在每一个实体,属性和关系数据模型,可以通过用户信息访问方法NSEntityDescription实例。
Xcode's data modelling tools give you access to this dictionary via the Data Model Inspector's "User Info" group. When editing a data model, you can open this inspector using Xcode's menus — View > Utilities > Show Data Model Inspector, or press ⌥⌘3 on your keyboard.
Xcode的数据建模工具给你访问这个字典通过数据模型检查器的“用户信息”。在编辑一个数据模型时,您可以使用Xcode的菜单,打开这个检查员视图>工具>显示数据模型检查器,或按⌥⌘3键盘上。
By default, MagicalRecord will automatically try to match attribute and relationship names with the keys in your imported data. If an attribute or relationship name in your model matches a key in your data, you don't need to do anything — the value attached to the key will be imported automatically.
默认情况下,MagicalRecord会自动尝试匹配键的属性和关系名称您导入的数据。如果一个属性或关系名称在您的数据模型匹配的关键,你不需要做任何事情——价值将自动导入的关键。
For example, if an attribute on an entity has the name 'firstName', MagicalRecord will assume the key in the data to import will also have a key of 'firstName' — if it does, your entity's firstName attribute will be set to the value of the firstName key in your data.
举个例子,如果一个属性对一个实体的名字“firstName”,MagicalRecord假设关键数据的导入也将一个关键的“firstName”——如果是这样,你的实体firstName属性的值将被设置为firstName的关键数据。
More often than not, the keys and structure in the data you are importing will not match your entity's attributes and relationships. In this case, you will need to tell MagicalRecord how to map your import data's keys to the correct attribute or relationship in your data model.
往往,钥匙和结构数据的导入不会匹配您的实体的属性和关系。在这种情况下,您将需要告诉MagicalRecord如何导入数据的键映射到正确的属性或关系数据模型。
Each of the three key objects we deal with in Core Data — Entities, Attributes and Relationships — have options that may need to be specified via user info keys:
我们每三个关键对象的处理核心数据——实体,属性和关系,选项可能通过用户信息需要指定键:
Attributes

Attributes.png

Entities
Entities.png

Relationships
Relationships.png

Importing Objects 进口物品
To import data into your store using MagicalRecord, you need to know two things:
使用MagicalRecord数据导入到你的店铺,你需要知道两件事:

  1. The format of the data you're importing, and how it
    The basic idea behind MagicalRecord's importing is that you know the entity the data should be imported into, so you then write a single line of code tying this entity with the data to import. There are a couple of options to kick off the import process.
    你导入的格式数据,以及它如何MagicalRecord背后的基本理念的导入,你知道实体应该导入的数据,所以你写一行代码将这个实体的数据导入。有一些选项来启动导入过程。
    To automatically create a new instance from the object, you can use the following, shorter approach:
    自动创建一个新实例的对象,您可以使用以下,较短的方法:
NSDictionary *contactInfo = // Result from JSON parser or some other source

Person *importedPerson = [Person MR_importFromObject:contactInfo];

You can also use a two-stage approach:
您还可以使用一个两阶段的方法:

NSDictionary *contactInfo = // Result from JSON parser or some other source

Person *person = [Person MR_createEntity]; // This doesn't have to be a new entity
[person MR_importValuesForKeysWithObject:contactInfo];

The two-stage approach can be helpful if you’re looking to update an existing object by overwriting its attributes.
两阶段方法可以帮助如果你想通过覆盖更新现有对象的属性。
+MR_importFromObject: will look for an existing object based on the configured lookup value (see the relatedByAttribute andattributeNameID). Also notice how this follows the built in paradigm of importing a list of key-value pairs in Cocoa, as well as following the safe way to import data.
+MR_importFromObject:将寻找现有对象的基础上,查找配置值(见relatedByAttribute attributeNameID)。也注意到此前范式的建立进口可可豆中的键值对列表,以及导入数据的安全方法。
The +MR_importFromObject: class method provides a wrapper around creating a new object using the previously mentioned-MR_importValuesForKeysWithObject: instance method, and returns the newly created object filled with data.
+MR_importFromObject:类方法提供了一个包装使用前面提到的-MR_importValuesForKeysWithObject:创建一个新的对象实例方法,并返回新创建的对象数据。
A key item of note is that both these methods are synchronous. While some imports will take longer than others, it’s still highly advisable to perform all imports in the background so as to not impact user interaction. As previously discussed, MagicalRecord provides a handy API to make using background threads more manageable:
注意的是,这两种方法的一个关键项是同步的。虽然一些进口将比别人花费更多的时间,它仍然是高度建议执行所有进口的背景,以便不影响用户交互。正如前面所讨论的那样,MagicalRecord提供了一个方便的API来使用后台线程更易于管理:

[MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *)localContext {
  Person *importedPerson = [Person MR_importFromObject:personRecord inContext:localContext];
}];```

>**Importing Arrays 输入数组**
It’s common for a list of data to be served using a JSON array, or you’re importing a large list of a single type of data. The details of importing such a list are taken care of in the +MR_importFromArray: class method.
公共的数据是使用JSON数组,或者你导入一个大型的单一类型的数据列表。进口的细节中照顾这样一个列表+ MR_importFromArray:类方法。

NSArray *arrayOfPeopleData = /// result from JSON parser
NSArray *people = [Person MR_importFromArray:arrayOfPeopleData];

This method, like +MR_importFromObject: is also synchronous, so for background importing, use the previously mentioned helper method for performing blocks in the background.   
这种方法,像+ MR_importFromObject:也是同步的,所以对于背景导入,使用前面提到的辅助方法用于执行块的背景。
If your import data exactly matches your Core Data model, then read no further because the aforementioned methods are all you need to import your data into your Core Data store. However, if your data, like most, has little quirks and minor deviations, then read on, as we’ll walk through some of the features of MagicalRecord that will help you handle several commonly encountered deviations.        
如果你导入数据完全匹配你的核心数据模型,然后阅读不再因为前面提到的方法都是需要你的数据导入到你的核心数据存储。最喜欢的,但是,如果您的数据小怪癖和轻微的偏差,然后继续读下去,当我们穿过的一些特性MagicalRecord会帮助你处理一些常见的偏差。

>**Best Practice    最佳实践**

>**Handling Bad Data When Importing 处理错误数据在导入**
APIs can often return data that has inconsistent formatting or values. The best way to handle this is to use the import category methods on your entity classes. There are three provided:      
api会返回数据格式不一致或值。处理这个问题的最好方法是使用进口的方法在你的实体类。提供有三种:
![Handling Bad Data When Importing.png](http://upload-images.jianshu.io/upload_images/1907575-255fc78b4e43c357.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
Generally, if your data is bad you'll want to fix what the import did after an attempt has been made to import any values.      
一般来说,如果您的数据是坏你要解决什么导入后一直尝试导入任何值。
A common scenario is importing JSON data where numeric strings can often be misinterpreted as an actual number. If you want to ensure that a value is imported as a string, you could do the following: 
一个常见的场景是进口JSON数据,数字字符串常常被误解为一个实际的数字。如果你想确保一个值是进口作为一个字符串,你可以做以下几点:

>```
>@interface MyGreatEntity

>@property(readwrite, nonatomic, copy) NSString *identifier;

>@end

>@implementation MyGreatEntity

>@dynamic identifier;

>- (void)didImport:(id)data
{
  if (NO == [data isKindOfClass:[NSDictionary class]]) {
    return;
}

  >NSDictionary *dataDictionary = (NSDictionary *)data;

  >id identifierValue = dataDictionary[@"my_identifier"];

  >if ([identifierValue isKindOfClass:[NSNumber class]]) {
    NSNumber *numberValue = (NSNumber *)identifierValue;
    self.identifier = [numberValue stringValue];
  }
}

>@end
>```

>**Deleting local records on import update  删除本地导入更新记录**
Sometimes you will want to make sure that subsequent import operations not only update but also delete local records that are not included as part of the remote dataset. To do this, fetch all local records not included in this update via theirrelatedByAttribute (id in the example below) and remove them immediately before importing the new dataset.   
有时你会想要确保后续导入操作不仅更新也删除本地记录,不包括作为远程数据集的一部分。为此,获取所有本地记录不包含在此更新通过relatedByAttribute在下面的例子中(id)和删除它们之前立即导入新数据集。

>```
NSArray *arrayOfPeopleData = /// result from JSON parser
NSArray *people = [Person MR_importFromArray:arrayOfPeopleData];
NSArray *idList = [arrayOfPeopleData valueForKey:@"id"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT(id IN %@)", idList];
[Person MR_deleteAllMatchingPredicate:predicate];

>```
If you also want to make sure that related records are removed during this update, you can use similar logic as above but implement it in the willImport: method of Person      
如果你也想要确保在这更新相关记录被删除,您可以使用类似的逻辑willImport如上,但实现它:方法的人
>```
>@implementation Person

>-(void)willImport:(id)data {
    NSArray *idList = [data[@"posts"] valueForKey:@"id"];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT(id IN %@) AND person.id == %@", idList, self.id];
    [Post MR_deleteAllMatchingPredicate:predicate];
}
>```
Source: http://stackoverflow.com/a/24252825/401092

- [Logging](https://github.com/magicalpanda/MagicalRecord/blob/master/Docs/Logging.md)

>**Logging  日志记录**
MagicalRecord has logging built in to most of its interactions with Core Data. When errors occur during fetching or saving data, these errors are captured and (if you've enabled them) logged to the console.  
MagicalRecord日志建立在与核心数据的交互。当错误发生在抓取或保存数据时,这些错误捕获和(如果你使他们)登录到控制台。
Logging is configured to output debugging messages (MagicalRecordLoggingLevelDebug) by default in debug builds, and will output error messages (MagicalRecordLoggingLevelError) in release builds.      
日志配置为默认输出调试信息(MagicalRecordLoggingLevelDebug)在调试构建,并将输出错误消息(MagicalRecordLoggingLevelError)发布构建。
Logging can be configured by calling [MagicalRecord setLoggingLevel:]; using one of the predefined logging levels:  
日志可以通过调用配置(MagicalRecord setLoggingLevel:];使用一个预定义的日志记录级别:
•   MagicalRecordLogLevelOff: Don't log anything    不要什么日志
•   MagicalRecordLoggingLevelError: Log all errors      记录所有错误
•   MagicalRecordLoggingLevelWarn: Log warnings and errors  日志警告和错误
•   MagicalRecordLoggingLevelInfo: Log informative, warning and error messages  日志信息,警告和错误消息
•   MagicalRecordLoggingLevelDebug: Log all debug, informative, warning and error messages  记录所有调试信息,警告和错误消息
•   MagicalRecordLoggingLevelVerbose: Log verbose diagnostic, informative, warning and error messages   日志详细的诊断信息,警告和错误消息
The logging level defaults to MagicalRecordLoggingLevelWarn.    
MagicalRecordLoggingLevelWarn日志级别默认值。

>**CocoaLumberjack**
If it's available, MagicalRecord will direct its logs to [CocoaLumberjack](https://github.com/CocoaLumberjack/CocoaLumberjack). All you need to do is make sure you've imported CocoaLumberjack before you import MagicalRecord, like so: 
如果可用,MagicalRecord将直接CocoaLumberjack的日志。所有你需要做的是确保进口CocoaLumberjack进口MagicalRecord之前,就像这样:

// Objective-C

import <CocoaLumberjack/CocoaLumberjack.h>

import <MagicalRecord/MagicalRecord.h>

// Swift
import CocoaLumberjack
import MagicalRecord


>**Disabling Logging Completely 完全禁用日志记录**
For most people this should be unnecessary. Setting the logging level to MagicalRecordLogLevelOff will ensure that no logs are printed. 
对大多数人来说这应该是不必要的。将日志级别设置为MagicalRecordLogLevelOff将确保不打印日志。
Even when using MagicalRecordLogLevelOff, a very quick check may be performed whenever a log call is made. If you absolutely need to disable the logging, you will need to define the following when compiling MagicalRecord:   
即使使用MagicalRecordLogLevelOff,快速检查可能只要一个日志调用执行。如果您绝对需要禁用日志记录,您将需要编译MagicalRecord时定义如下:

define MR_LOGGING_DISABLED 1 #定义MR_LOGGING_DISABLED 1```

Please note that this will only work if you've added MagicalRecord's source to your own project. You can also add this to the MagicalRecord project's OTHER_CFLAGS as -DMR_LOGGING_DISABLED=1.
请注意,这只会工作如果你MagicalRecord源添加到自己的项目。您还可以添加这个MagicalRecord项目的OTHER_CFLAGS -DMR_LOGGING_DISABLED = 1。

Resources 资源
The following articles highlight how to install and use aspects of MagicalRecord:
下面的文章强调如何MagicalRecord的安装和使用方面:
How to make Programming with Core Data Pleasant 如何使编程与核心数据愉快吗
Using Core Data with MagicalRecord 与MagicalRecord使用核心数据
Super Happy Easy Fetching in Core Data 超级快乐在核心数据容易获取
Core Data and Threads, without the Headache 核心数据和线程,没有头痛
Unit Testing with Core Data 单元测试与核心数据

**Support **支持

MagicalRecord is provided as-is, free of charge. For support, you have a few choices:
MagicalRecord是按原样提供的,免费的支持,你有几个选择:

  • Ask your support question on Stackoverflow.com, and tag your question with MagicalRecord. The core team will be notified of your question only if you mark your question with this tag. The general Stack Overflow community is provided the opportunity to answer the question to help you faster, and to reap the reputation points. If the community is unable to answer, we'll try to step in and answer your question.
    在Stackoverflow.com上问你的支持问题,并与MagicalRecord标记你的问题。核心团队将通知你的问题只有你和这个标签标记你的问题。一般的堆栈溢出社区提供机会回答问题来帮助你更快,并获得荣誉点。如果社区无法回答,我们将试图介入并回答你的问题。
  • If you believe you have found a bug in MagicalRecord, please submit a support ticket on the Github Issues page for MagicalRecord. We'll get to them as soon as we can. Please do NOT ask general questions on the issue tracker. Support questions will be closed unanswered.
    如果你相信你在MagicalRecord发现一个bug,请提交一个支持机票在Github MagicalRecord问题页面。我们会尽快。请不要问一般问题在问题跟踪器。支持将被关闭的问题回答。
  • For more personal or immediate support, MagicalPanda is available for hire to consult on your project.
    更多的个人或直接支持,MagicalPanda可供雇佣咨询您的项目。

**Twitter **推特

Follow @MagicalRecord on twitter to stay up to date with the latest updates relating to MagicalRecord.

在twitter上关注@MagicalRecord熬夜有关MagicalRecord最新的更新。

总结

不好意思了各位,可能你们读者有一些煎熬,没办法,英语水平就这样,还要加油。
写了这么多,还是感谢自己坚持了下来。但是事后查看了一些CoreData的相关文章,发现有大牛翻译好的中文文档,而且还是实时更新的。不多说了,附上中文文档:MagicalRecord中文文档

附录一些不错的DoreData学习文章:
小敏的博客coreData详解
蒋国纲的技术博客CoreData教程

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,198评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,663评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,985评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,673评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,994评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,399评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,717评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,407评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,112评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,371评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,891评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,255评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,881评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,010评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,764评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,412评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,299评论 2 260

推荐阅读更多精彩内容