使用RESTKit映射嵌套节点

时间:2014-07-11 09:42:21

标签: ios mapping restkit

我正在实施一个使用reddit Feed的简单iOS应用,我需要显示Feed评论。我正在使用RESTKit来执行ORM部分,我对映射注释感到烦恼。

Reddit评论可以有回复,回复可以有回复等等。这是一条评论树。这没什么大不了的。问题是在子节点中可能存在一个不同的节点(用于表示在该特定线程上有更多的注释要加载)。

这是一个JSON示例:

"replies":{
 "data":
  {
    "after": null,
    "before": null,
    "children": 
    [ 
     {
        "data":
        {
            "approved_by": null,
            "author": "InstaRamen",
            "author_flair_css_class": null,
            "author_flair_text": null,
            "banned_by": null,
            "body": "that or he counted it all wrong",
            "body_html":"<div class=\"md\"><p>that or he counted it all wrong</p>\n</div>",
            "controversiality": 0,
            "created": 1405093511,
            "created_utc": 1405064711,
            "distinguished": null,
            "downs": 0,
            "edited": false,
            "gilded": 0
            "id": "ciubfdk",
            "likes": null,
            "link_id": "t3_2ae8oa",
            "name": "t1_ciubfdk",
            "num_reports": null,
            "parent_id": "t1_ciuao19",
            "replies":
            {
                "data":
                {
                    "after": null,
                    "before": null,
                    "children":
                    [
                    {
                        "data":
                        {
                            "approved_by": null,
                            "author": "Everlasting",
                            "author_flair_css_class": null,
                            "author_flair_text": null,
                            "banned_by": null,
                            "body": "3, sir.",
                            "body_html":"<div class=\"md\"><p>3, sir.</p>\n</div>",
                            "controversiality": 0,
                            "created": 1405093986,
                            "created_utc": 1405065186,
                            "distinguished": null,
                            "downs": 0,
                            "edited": false,
                            "gilded": 0,
                            "id": "ciubj8h",
                            "likes": null,
                            "link_id": "t3_2ae8oa",
                            "name": "t1_ciubj8h",
                            "num_reports": null,
                            "parent_id": "t1_ciubfdk",
                            "replies":
                            {
                                "data":
                                {
                                    "after": null,
                                    "before": null,
                                    "children":
                                    [
                                    {
                                        "data":
                                        {
                                            "children":
                                            [
                                             "ciublgq"
                                            ],
                                            "count": 0,
                                            "id":"ciublgq",
                                            "name":"t1_ciublgq",
                                            "parent_id": "t1_ciubj8h"
                                        },
                                        "kind": "more"
                                    }
                                     ],
                                    "modhash": ""
                                },
                                "kind": "Listing"
                            },...

因此,您可以看到典型的评论回复具有

的结构
replies
  |-data
      |-children
            |-data 
               |- #comment key/values

但是“加载更多”项的结构为:

replies
  |-data
      |-children
            |-data 
                |-children
                |-more loading info...

我的DataObject是:

@interface RedditComment : NSObject

@property (nonatomic, copy) NSString *author;
@property (nonatomic, readwrite) NSInteger createdUTC;
@property (nonatomic, readwrite) NSInteger score;
@property (nonatomic, copy) NSString *subreddit;
@property (nonatomic, copy) NSString *subredditId;
@property (nonatomic, readwrite) NSInteger ups;
@property (nonatomic, copy) NSString *body;
@property (nonatomic, copy) NSArray *replies;

+ (RKObjectMapping*)restKitMapping;

@end

我的映射实现是:

@implementation RedditComment

+ (RKObjectMapping*)restKitMapping;
{
    RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[self class]];
    [mapping addAttributeMappingsFromDictionary:@{
                                              @"author":          @"author",
                                              @"created_utc":     @"createdUTC",
                                              @"score":           @"score",
                                              @"subreddit":       @"subreddit",
                                              @"subreddit_id":    @"subredditId",
                                              @"body":            @"body",
                                              @"ups":             @"ups",
                                              }];

 [mapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"replies" toKeyPath:@"replies" withMapping:mapping]];

 return mapping;
}
@end

这会产生错误:

 *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSCFConstantString 0x1daa0d0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key body.'

这是因为“加载更多”节点没有正文密钥(它也缺少其他密钥,但这是RESTKit抱怨的第一个)。

我尝试使用动态映射块来更改运行时的映射,但无法弄清楚如何隔离有问题的节点(即“加载更多”)。

我的问题是如何区分“回复”JSON节点中的两个可能值?

对于相同的部分密钥,我可以有两个映射吗? 这是回复&gt;的映射。数据&gt;儿童&gt;数据和另一个回复&gt;数据&gt;儿童&gt;数据&gt;子的。如果是这样怎么办?

或者我的思路有什么不妥?

提前感谢所有能够帮助或只是花时间阅读的人...; - )

修改 包括响应描述符

根据评论的要求,这里是RKResponseDescriptor:

RKResponseDescriptor *commentResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:[PPRedditComment restKitMapping]
                                                                                        method:RKRequestMethodAny
                                                                                   pathPattern:nil
                                                                                       keyPath:@"data"
                                                                                   statusCodes:nil];

编辑#2

包括一个“好评”节点,以显示我有兴趣映射到我的DO

"data":
{
"approved_by": null,
"author": "PerimeterBlue",
"author_flair_css_class":null,
"author_flair_text":null,
"banned_by":null,
"body": "This actually looks really cool.",
"body_html": "&lt;div class=\"md\"&gt;&lt;p&gt;This actually looks really cool.&lt;/p&gt;\n&lt;/div&gt;",
"controversiality":0,
"created": 1405095679,
"created_utc": 1405066879,
"distinguished":null,
"downs": 0,
"edited": false,
"gilded": 0,
"id": "ciubwld",
"likes":null,
"link_id": "t3_2aelr4",
"name": "t1_ciubwld",
"num_reports": null,
"parent_id": "t3_2aelr4",
"replies": {...},
"saved": false,
"score": 48,
"score_hidden": false,
"subreddit": "gaming",
"subreddit_id": "t5_2qh03",
"ups": 48
}

1 个答案:

答案 0 :(得分:0)

好的,显然有问题了。 Wain是对的:这是一个与道路相关的问题。

某些节点应该包含字典,有时包含字符串。在定义路径的方式中,这导致在NSString类上调用不存在的选择器(来自DO的属性)。因为它没有包含它,所以它就是BOOM!

映射已更正为:

+ (RKObjectMapping*)restKitMapping;
{
    RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[self class]];
    [mapping addAttributeMappingsFromDictionary:@{
                                              @"author":          @"author",
                                              @"created_utc":     @"createdUTC",
                                              @"score":           @"score",
                                              @"subreddit":       @"subreddit",
                                              @"subreddit_id":    @"subredditId",
                                              @"body":            @"body",
                                              @"ups":             @"ups",
                                              }];

    RKDynamicMapping *dynamicMapping = [RKDynamicMapping new];
    [dynamicMapping setObjectMappingForRepresentationBlock:^RKObjectMapping *(id representation) {

        RKObjectMapping *result = mapping; 

        // When node is empty string don't map...
        if([representation isKindOfClass:[NSString class]] && [representation isEqualToString:@""])
        {
            result = nil;
        }

        return result;
        }];

        [mapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"replies"
                                                                        toKeyPath:@"replies"
                                                                      withMapping:dynamicMapping]];

    return mapping;
}

响应描述符更正为:

RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:[PPRedditFeedCollection restKitMapping]
                                                                                        method:RKRequestMethodAny
                                                                                   pathPattern:nil
                                                                                       keyPath:@"data"
                                                                                   statusCodes:nil];

希望这有助于某人! : - )