在开始之前,我们先创建一个名为MemberManaged的实体
MemberManaged.h
1
2
3
4
5
6
7
8
| @interface MemberManaged : NSManagedObject
@property (nonatomic, retain) NSString * memberID;
@property (nonatomic, retain) NSString * mobilePhone;
@property (nonatomic, retain) NSDate * createDate;
@property (nonatomic, retain) NSNumber * goldNumber;
@property (nonatomic, retain) NSNumber * age;
@property (nonatomic, retain) NSNumber * isVip;
@property (nonatomic, retain) NSString * url;
|
后续的例子都是以此实体进行数据库的操作
快速入门
配置
1
2
3
4
5
6
7
8
9
10
| - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[MagicalRecord setupAutoMigratingCoreDataStack];
// ...
return YES;
}
- (void)applicationWillTerminate:(UIApplication *)application
{
[MagicalRecord cleanUp];
}
|
查找数据
1
2
| //返回MemberManaged表中的第一条数据
MemberManaged *memberManaged = [MemberManaged MR_findFirst];
|
1
2
| //返回MemberManaged表中的所有数据
NSArray *array = [[MemberManaged MR_findAll];
|
1
2
| //键值条件查找,返回符合条件的所有数据
NSArray *array = [MemberManaged MR_findByAttribute:@"memberID" withValue:@"1"];
|
1
2
| //按指定字段排序
NSArray *array = [MemberManaged MR_findAllSortedBy:@"age" ascending:YES];
|
1
2
3
| //自定义NSPredicate查找,返回符合条件的所有数据
NSPredicate *pre = [NSPredicate predicateWithFormat:@"age > 18"];
MemberManaged *memberManaged = [MemberManaged MR_findAllWithPredicate:pre];
|
对于NSPredicate不熟悉的同学可以看我之前写的介绍NSPredicate的博文,关于其他的查找方法我就不一一介绍了。
插入数据
1
2
3
4
5
6
7
8
9
10
11
12
13
| [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
MemberManaged *memberManaged = [MemberManaged MR_createInContext:localContext];
memberManaged.memberID = @"1";
memberManaged.mobilePhone = @"xxxxxxxx";
memberManaged.createDate = [NSDate date];
memberManaged.goldNumber = @2;
memberManaged.age = @18;
memberManaged.url = @"http://bawn.github.io/";
memberManaged.isVip = @YES;
} completion:^(BOOL success, NSError *error) {
// ...
}];
|
删除数据
1
2
3
4
5
6
7
| //删除单条数据
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
MemberManaged *member = [MemberManaged MR_findFirstInContext:localContext];
[member MR_deleteEntity];
} completion:^(BOOL success, NSError *error) {
// ...
}];
|
1
2
3
4
5
6
| //删除表
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
[MemberManaged MR_truncateAllInContext:localContext];
} completion:^(BOOL success, NSError *error) {
// ...
}];
|
更新数据
1
2
3
4
5
6
7
| MemberManaged *member = [MemberManaged MR_findFirst];
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
MemberManaged *localMember = [member MR_inContext:localContext];
localMember.age = @22;
} completion:^(BOOL success, NSError *error) {
// ...
}];
|
配合Mantle
基本转换
上一篇 博文 中提到Mantle的 MTLManagedObjectAdapter 类,2.0版本开发者已把此类作为一个单独 repo 从 Mantle 剥离出来,这个类有个名叫MTLManagedObjectSerializing
的协议,此协议有两个必须实现的方法:
1
2
| //返回此类对应的实体类名
+ (NSString *)managedObjectEntityName;
|
1
2
| //返回此类和实体属性的映射关系
+ (NSDictionary *)managedObjectKeysByPropertyKey;
|
另外由于Member类和MemberManaged类的url字段的类型不一致,需要实现另一个协议方法,实现NSUrl
–>NSString
(age和isVip字段不需要转换,不要问我为什么)
1
2
| //属性值转换
+ (NSValueTransformer *)entityAttributeTransformerForKey:(NSString *)key;
|
先看具体实现
Member.h
1
2
3
4
5
6
7
8
| @interface Member : MTLModel<MTLJSONSerializing, MTLManagedObjectSerializing>
@property (nonatomic, retain) NSString * memberID;
@property (nonatomic, retain) NSString * mobilePhone;
@property (nonatomic, retain) NSDate * createDate;
@property (nonatomic, retain) NSNumber *goldNumber;
@property (nonatomic, assign) NSUInteger age;
@property (nonatomic, assign) BOOL isVip;
@property (nonatomic, retain) NSURL *url;
|
Member.m
1
2
3
4
| //表示Member类对应的实体类是MemberManaged
+ (NSString *)managedObjectEntityName{
return @"MemberManaged";
}
|
1
2
3
4
5
6
7
8
9
10
11
12
| //表示Member类向MemberManaged类转换的字段映射,也是需要写全的
+ (NSDictionary *)managedObjectKeysByPropertyKey{
return @{
@"memberID" : @"memberID",
@"mobilePhone" : @"mobilePhone",
@"createDate" : @"createDate",
@"goldNumber" : @"goldNumber",
@"age" : @"age",
@"isVip" : @"isVip",
@"url" : @"url"
};
}
|
具体运用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| NSDictionary *dic = @{
@"id" : @"2",
@"phone" : @"xxxxxxxx",
@"date" : @"2014-09-09",
@"goldNumber" : @2,
@"age" : @"18",
@"url" : @"http://bawn.github.io/",
@"isVip" : NSNull.null
};
Member *member = [MTLJSONAdapter modelOfClass:[Member class] fromJSONDictionary:dic error:nil];
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
[MTLManagedObjectAdapter managedObjectFromModel:member insertingIntoContext:localContext error:nil];
} completion:^(BOOL success, NSError *error) {
NSLog(@"%lu", (unsigned long)[MemberManaged MR_findAll].count);
}];
|
Member *member = [MTLJSONAdapter modelOfClass:[Member class] fromJSONDictionary:dic error:nil];
完成从NSDictionary–>Member转换,并返回Member实例[MTLManagedObjectAdapter managedObjectFromModel:member insertingIntoContext:localContext error:nil];
完成Member–>MemberManaged转换,返回MemberManaged实例,但是我们并不需要。- 配合MagicalRecord储存方法
+ (void) saveWithBlock:(void(^)(NSManagedObjectContext *localContext))block;
注意:对于MemberManaged类,我们并不需要对它做任何的处理。
唯一性检查
同样是实现<MTLManagedObjectSerializing>
中的一个方法:
1
2
3
| + (NSSet *)propertyKeysForManagedObjectUniquing{
return [NSSet setWithObject:@"memberID"];
}
|
表示当插入新数据的时候,对比需要插入的这条数据的memberID字段的值是否和数据库中的有相同。如果有相同就覆盖更新这条数据,如果没有就新增。这样带来的方便之处显而易见。
更新数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
- (IBAction)updateData:(id)sender{
NSDictionary *dic = @{
@"id" : @"2",
@"phone" : @"xxxxxxxx",
@"date" : @"2015-12-09",
@"goldNumber" : @2,
@"age" : @"19",
@"url" : @"http://bawn.github.io/",
@"isVip" : NSNull.null
};
Member *member = [MTLJSONAdapter modelOfClass:[Member class] fromJSONDictionary:dic error:nil];
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
[MTLManagedObjectAdapter managedObjectFromModel:member insertingIntoContext:localContext error:nil];
} completion:^(BOOL success, NSError *error) {
NSLog(@"%lu", (unsigned long)[MemberManaged MR_findAll].count);
}];
}
|
数据库中只有一条数据,因为插入的数据的memberID都是2。
总结
MagicalRecord配合Mantle使用至少让代码看起来简洁了不少,再也不用为Core Data复杂的API而烦恼,也不用再写if/else来做字段的转换。
Demo地址:MagicalRecord-Mantle