OHMKit 使得从网络服务或本地文件中提取 Objective-C 模型对象更容易。它与 JSON 配置得非常好。它类似于 Mantle 和 JSONModel,但是 OHMKit 不需要模型继承自基类,因此更适合与 Core Data、Parse、Realm 或其他需要从基类继承的库一起使用。
OHMKit 是一个用于声明式地指定如何将数据从 JSON 或 plist 转换为本地 Objective-C 模型对象的系统。OHMKit 不需要模型继承自基类,因此它可以与 NSObjects、NSManagedObjects 或类层次结构中的任何其他内容一起工作。您可以在任何地方指定自定义映射,而不仅仅是模型中。因此,您可以将将服务映射到模型的相关细节从模型代码中分离出来,放入更合适的服务代码中。
将此 JSON
{
"name": "Fabian",
"favorite_word": "absurd",
"favorite_number": 47
}
插入此对象
@interface MYModel : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *favoriteWord;
@property (nonatomic, assign) NSInteger favoriteNumber;
@end
将您的 Web 服务中的 user_name
映射到 Objective-C 模型中的 userName
。将数字字典映射到 UIColor
。或者使用单行代码来提取整个层级结构化的 JSON 响应,其中包括数组、字典,以及任意深度的真实 Objective-C 对象...
OHMKit 存在的原因是 RestKit (话说,这是一个很棒的工具),有时太大、太重、太不直接。因为 Mantle 和 JSONModel 需要模型继承自基类。
因为有时候,您的代码消耗的网络服务与您的模型对象不完全匹配。
OHMKit 是一个少于 200 行的代码,正在被数百万用户使用的应用程序商店中的应用程序所采用。
OHMKit 不懂网络,请使用 AFNetworking。
OHMKit 不懂路由,请使用 SOCKit。
OHMKit 不懂 JSON,请使用 NSJSONSerialization
OHMKit 不懂 CoreData。它不会像 RestKit 一样为您管理实体图。但是 OHMKit 不关心您的模型类的基类。因此,您可以安全地创建 NSManagedObject
的子类,以便可映射。
给定一个模型
@interface MYModel : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *favoriteWord;
@property (nonatomic, assign) NSInteger favoriteNumber;
@end
在任何应用中的位置,使模型可映射,并将其分配一个字典,该字典包含服务将提供的键与您的实际模型对象使用的键之间的映射。
OHMMappable([MYModel class]);
OHMSetMapping([MYModel class], @{@"favorite_word" : @"favoriteWord",
@"favorite_number": @"favoriteNumber");
现在,在您的应用中的任何位置,MYModel
类的对象都可以从一个字典中填充数据,该字典将由您提供的映射字典进行转换。
MYModel *testModel = [[MYModel alloc] init];
[testModel setValuesForKeysWithDictionary:@{@"name" : @"Fabian",
@"favorite_word" : @"absurd",
@"favorite_number": @47];
可映射对象的递归映射是免费的。如果一个符合 <OMMappable>
的对象有一个类型也符合 <OMMappable>
的属性,并且 hydration 字典中该键的值是一个字典,我们将实例化一个新的模型对象并填充它。
@interface MYClass : NSObject
@property (nonatomic, strong) NSString *name;
@end
@interface MYClass2 : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *favoriteWord;
@property (nonatomic, assign) NSInteger favoriteNumber;
@property (nonatomic, assign) MYClass *favoriteObject;
@end
OHMMappable([MYClass class]);
OHMMappable([MYClass2 class])
OHMSetMapping([MYClass2 class], @{@"favorite_word" : @"favoriteWord",
@"favorite_number": @"favoriteNumber",
@"favorite_object" : @"favoriteObject"});
MYModel *testModel = [[MYClass2 alloc] init];
NSDictionary *class2Response = @{@"name" : @"Fabian",
@"favorite_word" : @"absurd",
@"favorite_number": @2,
@"favorite_object": @{@"name" : @"Rock"}};
[testModel setValuesForKeysWithDictionary:class2Response];
现在,testModel.favoriteObject
是一个 MYClass
实例,其名称被水分化(hydrated)为 "Rock"。
内部,新的模型对象使用 [[ alloc] init]
初始化,然后使用 [setValuesForKeysWithDictionary:dictionary]
进行填充。如果您有需要特殊初始化考虑的模型,请使用适配器块。
可以也将字典数组映射到一个类中。
@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
@end
@interface Roster : NSObject
@property (nonatomic, strong) NSArray *people;
@end
OHMMappable([Person class]);
OHMSetArrayClasses([Roster class], @{@"people":[Person class]});
NSDictionary *response = @{@[@{@"name":@"Bert"},
@{@"name":@"Ernie"},
@{@"name":@"Count"}];
Roster *roster = [Roster new];
[roster setValuesForKeysWithDictionary:response];
用户可以为需要特殊处理的字段传递一个块的字典。比如说,一个服务返回的字典看起来像这样:
{
"favorite_color": [
122,
50,
80
],
"least_favorite_color": [
121,
51,
81
]
}
我们希望将其映射到这样模式的模型中:
@interface MYModel : NSObject
@property (nonatomic, strong) UIColor *favoriteColor;
@property (nonatomic, strong) UIColor *leastFavoriteColor;
@end
您可以使用适配器块来适配响应
OHMMappable([MYModel class]);
OHMSetMapping([MYModel class], @"least_favorite_color" : @"leastFavoriteColor", @"favorite_color" : @"favoriteColor")
OHMValueAdapterBlock colorFromNumberArray = ^(NSArray *numberArray) {
return [UIColor colorWithRed:[numberArray[0] integerValue]/255.0
green:[numberArray[1] integerValue]/255.0
blue:[numberArray[2] integerValue]/255.0
alpha:1];
};
OHMSetAdapter([MYModel class], @{@"favoriteColor": colorFromNumberArray, @"leastFavoriteColor": colorFromNumberArray});
注意,适配器的键是模型对象上的键,而不是响应上的键。适配器是为属性添加的,而不是类型。如果上面的例子中有多个属性是颜色,您必须为每个属性设置一个适配器块。在您的代码中重用适配器块是明智的。
OHMValueAdapterBlock
类型是一个接收一个 id
并返回一个 id
的块。即 typedef id(^OHMValueAdapterBlock)(id);
使用 CocoaPods,将 OHMKit 添加到您的 PodFile
中,然后运行 $ pod install
pod 'OHMKit'
OHMKit 是一个 混合型功能模块(Mixin),它使您能够非常轻松地将您正在使用的服务的特性保留在一个地方。
它利用了 Cocoa 中内置的键值编码(KVC)的强大功能。它安全地包装了 -setValue:forKey:
和 -setValue:forUndefinedKey:
以使对 setValuesForKeysWithDictionary:
的调用非常强大。
欢迎提交修复错误、合并请求、增强请求和反馈。
如果您打算提交代码,请注意 OHMKit 有测试。如果您正在修复错误,请包括一个测试,该测试可以暴露错误并因此防止回归。
未定义键的行为应在3个级别上进行可配置
选项 2 目前是唯一的行为,而且我倾向于将其保留为默认行为。
如果我们能够创建一种让非NSCoding
类兼容的方法,那将是一件好事。我喜欢Mantle,但我不想被告知我的超类应该是哪个。
适配器代码块与NSValueTransformer
可以并存,这是没有理由不能的。
Copyright (c) 2013-2015 Fabian Canas. All rights reserved.
This code is distributed under the terms and conditions of the MIT license.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.