如何让YapDatabase和Mantle与序列化很好地配合

时间:2014-05-23 20:58:50

标签: ios objective-c github-mantle yapdatabase

假设我有这样的模型:

#import <Mantle/Mantle.h>
#import "MyCustomObject.h"
@interface MyModel : MTLModel <MTLJSONSerializing>
@property (nonatomic, copy, readonly) NSString *UUID;
@property (nonatomic, copy) NSString *someProp;
@property (nonatomic, copy) MyCustomObject *anotherProp;
@end

#import "MyModel.h"
@implementation MyModel
+ (NSDictionary *)JSONKeyPathsByPropertyKey
{
        return @{
            @"UUID": @"id",
            @"anotherProp": NSNull.null
    };
}
}
@end

如您所见,我想在NSCoding序列化期间忽略anotherProp,以及重新映射&#34; UUID&#34;到&#34; id&#34;。使用YapDatabase,我做了

[transaction setObject:myModelObj forKey:@"key_1" inCollection:@"my_collection"]

但它尝试序列化anotherProp,尽管我使用了自定义JSONKeyPathsByPropertyKey方法,导致此错误:

*** Caught exception encoding value for key "anotherProp" on class MyModel: -[YapDatabase encodeWithCoder:]: unrecognized selector sent to instance 0xc989630

我是否需要编写自定义序列化程序才能让YapDatabase使用JSONKeyPathsByPropertyKey

2 个答案:

答案 0 :(得分:1)

您需要配置YapDatabase以使用Mantle。默认情况下,它将使用NSCoding。 (这就是为什么你会看到关于&#34; encodeWithCoder:&#34;的错误,因为该方法是NSCoding的一部分。)

查看YapDatabase的wiki文章,名为&#34; Storing Objects&#34;,它讨论了它如何使用序列化器/反序列化器块: https://github.com/yaptv/YapDatabase/wiki/Storing-Objects

基本上,当你分配/初始化你的YapDatabase实例时,你想要传递一个序列化器&amp;反序列化程序块,它使用Mantle执行序列化/反序列化。

另外,请参阅YapDatabase可用的各种init方法: https://github.com/yaptv/YapDatabase/blob/master/YapDatabase/YapDatabase.h

答案 1 :(得分:0)

这是我目前的方法,使用MTLModel扩展来使这个“正常工作”没有序列化程序或任何东西。如果有一个串行器实现或更好的东西,请告诉我。否则,这段代码可以节省生命:

// JSONEncodableMTLModel.h
#import <Foundation/Foundation.h>
#import "Mantle.h"

@interface JSONEncodableMTLModel : MTLModel <MTLJSONSerializing>    
+ (NSSet*)propertyKeysToExcludeInDictionaryValue;
@end

//  JSONEncodableMTLModel.m
#import "JSONEncodableMTLModel.h"
#import <objc/runtime.h>

@implementation JSONEncodableMTLModel

+(NSDictionary *)JSONKeyPathsByPropertyKey {
    return @{};
}

+ (NSSet*)propertyKeysToExcludeInDictionaryValue
{
    return [NSSet set];
}

// this is required to ensure we don't have cyclical references when including the parent variable.
+ (NSSet *)propertyKeys {
    NSSet *cachedKeys = objc_getAssociatedObject(self, HSModelCachedPropertyKeysKey);
    if (cachedKeys != nil) return cachedKeys;

    NSMutableSet *keys = [NSMutableSet setWithSet:[super propertyKeys]];

    NSSet *exclusionKeys = [self propertyKeysToExcludeInDictionaryValue];
    NSLog(@"Caching Your Property Keys");
    [exclusionKeys enumerateObjectsUsingBlock:^(NSString *propertyKey, BOOL *stop) {
        if([keys containsObject: propertyKey])
        {
            [keys removeObject: propertyKey];
        }
    }];

    // It doesn't really matter if we replace another thread's work, since we do
    // it atomically and the result should be the same.
    objc_setAssociatedObject(self, HSModelCachedPropertyKeysKey, [keys copy], OBJC_ASSOCIATION_COPY);

    return keys;
}

@end

使用此代码,我可以通过在任何子类模型中覆盖propertyKeysToExcludeInDictionaryValue来显式设置不需要序列化的属性。积分转到Stephen O'Connor