2013/12/12

MantleでObjective-CプロパティとJSON文字列との相互変換を自分で制御する

以前紹介したMantleのTipです。

Mantleを使えば、モデル内ではUIColorを用いておいて、JSONに保存するときはHTMLのように#eecad9みたいに出力させる、なんてことが割と簡単にできます。

例えば次のようなモデルがあったときに、

@interface FOOSampleModel : MTLModel<MTLJSONSerializing>
@property (assign, nonatomic) UIColor* textColor;
@end

+ (MTLValueTransformer*)textColorJSONTransformerを実装すればよいです。

Mantleでは「キー名+JSONTransformer」を実装すると自動でそのプロパティとJSONの相互変換するようになります。

あとはその中身を書くだけです (ちょっと長いですが)。

戻り値としてNSValueTransformerを返す必要がありますが、Mantle的には MTLValueTransformerでデシリアライズとシリアライズを実行するblockをそれぞれ書いてやればよいです。

+ (NSValueTransformer*)textColorJSONTransformer {
    return [MTLValueTransformer reversibleTransformerWithForwardBlock:^(NSString* string) {
        NSError* error = nil;
        NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:@"^#([0-9a-f]{6})$" options:NSRegularExpressionCaseInsensitive error:&error];
        NSArray* matches = [regex matchesInString:string options:0 range:NSMakeRange(0, [string length])];
        if (matches.count != 1) return [UIColor blackColor];

        NSTextCheckingResult* m = matches[0];
        NSString* col = [string substringWithRange:[m rangeAtIndex:1]];
        NSScanner* scanner = [NSScanner scannerWithString:col];
        unsigned int result = 0;
        [scanner scanHexInt:&result];

        CGFloat red   = ((result>>16) & 0xff) / 255.0f;
        CGFloat green = ((result>>8)  & 0xff) / 255.0f;
        CGFloat blue  = (result       & 0xff) / 255.0f;
        return [UIColor colorWithRed:red green:green blue:blue alpha:1.0f];
    } reverseBlock:^(UIColor* color) {
        CGFloat red, green, blue, alpha;
        [color getRed:&red green:&green blue:&blue alpha:&alpha];
        int r = (int) (red   * 255);
        int g = (int) (green * 255);
        int b = (int) (blue  * 255);
        return [NSString stringWithFormat:@"#%02x%02x%02x", r, g, b];
    }];
}

試しにシリアライズしてみましょう。

FOOSampleModel* model = [[FOOSampleModel alloc] init];
model.textColor = [UIColor purpleColor];
NSDictionary* dic = [MTLJSONAdapter JSONDictionaryFromModel:model];
NSLog(@"%@", dic);

シリアライズできました。

2013-12-12 01:16:27.257 XcodeSample[22519:70b] {
    textColor = "#7f007f";
}

コードは省略しますが、デシリアライズもちゃんとできます。

2013-12-12 01:16:10.506 XcodeSample[22519:70b] des: <FOOSampleModel: 0x8c97510> {
    textColor = "UIDeviceRGBColorSpace 0.498039 0 0.498039 1";
}

関連リンク

0 件のコメント:

コメントを投稿

注: コメントを投稿できるのは、このブログのメンバーだけです。