2013-12-09 45 views
4

我想用套框架(https://github.com/github/Mantle)支持NSCoding我的类结构特性:编码C-结构与地幔(NSCoding)

typedef struct { 
    int x; 
    int y; 
} MPoint; 

typedef struct { 
    MPoint min; 
    MPoint max; 
} MRect; 


@interface MObject : MTLModel 

@property (assign, nonatomic) MRect rect; 

@end 

@implementation MObject 
@end 

但是,当我试图​​其MTLModel + NSCoding坠毁.M,在- (void)encodeWithCoder:(NSCoder *)coder线

case MTLModelEncodingBehaviorUnconditional: 
    [coder encodeObject:value forKey:key]; 

不幔支持C-结构编码(和解码也)或我需要实施用于这些类NSCoding协议自定义?

回答

4

这比我想象的要简单:

  1. 排除财产+encodingBehaviorsByPropertyKey
  2. 人工编码/编码除外财产

样品:

#pragma mark - MTLModel + NSCoding 

- (id)initWithCoder:(NSCoder *)coder { 
    self = [super initWithCoder:coder]; 
    if (self) { 
     self.rect = [[self class] mRectFromData:[coder decodeObjectForKey:@"rectData"]]; 
    } 
    return self; 
} 

- (void)encodeWithCoder:(NSCoder *)coder { 
    [super encodeWithCoder:coder]; 

    [coder encodeObject:[[self class] dataFromMRect:self.rect] forKey:@"rectData"]; 
} 

+ (NSDictionary *)encodingBehaviorsByPropertyKey { 
    NSDictionary *excludeProperties = @{ 
             NSStringFromSelector(@selector(rect)): @(MTLModelEncodingBehaviorExcluded) 
             }; 
    NSDictionary *encodingBehaviors = [[super encodingBehaviorsByPropertyKey] mtl_dictionaryByAddingEntriesFromDictionary:excludeProperties]; 
    return encodingBehaviors; 
} 

#pragma mark - MRect transformations 

+ (MRect)mRectFromData:(NSData *)rectData { 
    MRect rect; 
    [rectData getBytes:&rect length:sizeof(rect)]; 
    return rect; 
} 

+ (NSData *)dataFromMRect:(MRect)rect { 
    return [NSData dataWithBytes:&rect length:sizeof(rect)]; 
} 
+0

一个可逆的值转换器会该房产的正确解决方案,如Sasha Zats示例 – GreatWiz

+0

@GreatWiz这将适用于JSON/XML编码,但不会在NSCoding期间被调用。使用中间值来表示结构似乎是[首选方法](https://github.com/Mantle/Mantle/issues/44)。 –

+0

@fa您链接的答案提到外部表示 – GreatWiz

4

我的原始数据结构是XML(是的,我知道):

... 
    <Lat>32.062883</Lat> 
    <Lot>34.782904</Lot> 
    ... 

我用MTLXMLAdapter基于KissXML,但你可以看到它是如何适用于任何其他串行器。

+ (NSValueTransformer *)coordinateXMLTransformer { 
    return [MTLValueTransformer reversibleTransformerWithBlock:^id(NSArray *nodes) { 
     CLLocationCoordinate2D coordinate; 
     for (DDXMLNode *node in nodes) { 
      if ([[node name] isEqualToString:@"Lat"]) { 
       coordinate.latitude = [[node stringValue] doubleValue]; 
      } else if ([[node name] isEqualToString:@"Lot"]) { 
       coordinate.longitude = [[node stringValue] doubleValue]; 
      } 

     } 
     return [NSValue value:&coordinate 
       withObjCType:@encode(CLLocationCoordinate2D)]; 
    }]; 
} 

如果需要,您可以添加reverseBlock