0

次のようなモデルがあるとします。

#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

ご覧のとおりanotherProp、NSCoding のシリアル化中は無視し、「UUID」を「id」に再マップします。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か?

4

2 に答える 2

1

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にあります。

于 2014-05-28T06:15:55.013 に答える
1

Mantle を使用するには YapDatabase を設定する必要があります。デフォルトでは、NSCoding を使用します。(これが、"encodeWithCoder:" に関するエラーが表示される理由です。このメソッドは NSCoding の一部であるためです。)

YapDatabase の wiki 記事「Storing Objects」を参照してください。この記事では、シリアライザー/デシリアライザー ブロックの使用方法について説明しています: https://github.com/yaptv/YapDatabase/wiki/Storing-Objects

基本的に、YapDatabase インスタンスを割り当て/初期化するときは、Mantle を使用してシリアライゼーション/デシリアライゼーションを実行するシリアライザーとデシリアライザー ブロックを渡す必要があります。

また、YapDatabase で使用できるさまざまな init メソッドを参照してください: https://github.com/yaptv/YapDatabase/blob/master/YapDatabase/YapDatabase.h

于 2014-05-23T21:50:25.997 に答える