RestKit .22:无法成功映射与嵌套JSON的关系

时间:2013-12-15 21:42:58

标签: ios rest restkit restkit-0.20

我几天来一直在和RestKit进行关系映射。我可以很好地获得单个对象,但是嵌套的JSON数据数组没有被映射并且查看跟踪日志我找不到任何错误。尽管它很痛,但我承认它已经让我受益匪浅。我尽可能多地查看了一些示例,并根据其他人在他们的情况下所做的事情尝试了不同的解决方案但没有任何工作。我试图遵循RestKit文档附带的RKGist示例,但不幸的是关于关系映射的部分尚未编写,那里只有占位符。

这是我正在使用的JSON示例响应:

{
"stat": {
    "code": 200
},
"data": {
    "channel": {
        "_id": "68413dzz39f4843t8500000d",
        "desc": "...",
        "name": "...",
        "owner": {
            "_id": "584ege8239f4883f6200000b",
            "name": "..."
        },
        "count": {
            "invited": 0,
            "joined": 1,
            "subscribers": 0,
            "posts": 0,
            "messages": 0
        },
        "access": "PUB"
    },
    "affiliation": "...",
    "member_statuses": [
        {
            "channel": {
                "_id": "68413dzz39f4843t8500000d",
                "name": "..."
            },
            "owner": {
                "_id": "584ege8239f4883f6200000b",
                "dname": "...",
                "name": "..."
            },
            "type": "...",
            "message": "This is the message text",
            "_id": "52222e3039f4884tkk00000e",
            "taken": "2013-11-11T20:23:45.938Z",
            "access": "PUB"
        }
    ]
}
}

我还无法发布图片,因为这是我无法找到答案的第一个问题。但是两个相关的Core Data模型和NSManagedObject子类是:

THChannel.h

我建立了一个名为posts的关系,其目的地为THPost,倒数为post。我选择类型为To Many,因为多个帖子可以属于一个频道

@class THPost, THUser;

@interface THChannel : NSManagedObject

@property (nonatomic, retain) NSString * accessCode;
@property (nonatomic, retain) NSString * channelId;
@property (nonatomic, retain) NSNumber * countComments;
@property (nonatomic, retain) NSNumber * countInvited;
@property (nonatomic, retain) NSNumber * countJoined;
@property (nonatomic, retain) NSNumber * countMessages;
@property (nonatomic, retain) NSNumber * countPhotos;
@property (nonatomic, retain) NSNumber * countPosts;
@property (nonatomic, retain) NSNumber * countSubscribers;
@property (nonatomic, retain) NSDate * createdAt;
@property (nonatomic, retain) NSString * desc;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) THUser *owner;
@property (nonatomic, retain) NSSet *posts;
@end

@interface THChannel (CoreDataGeneratedAccessors)

- (void)addPostsObject:(THPost *)value;
- (void)removePostsObject:(THPost *)value;
- (void)addPosts:(NSSet *)values;
- (void)removePosts:(NSSet *)values;

@end

THPost.h

我建立了一个名为post的关系,其目的地为THChannel,倒数为posts。我选择类型为To One,因为多个帖子可以属于一个频道

@class THChannel, THUser;

@interface THPost : NSManagedObject

@property (nonatomic, retain) NSString * postId;
@property (nonatomic, retain) NSString * channelId;
@property (nonatomic, retain) NSString * ownerTypeCode;
@property (nonatomic, retain) NSString * ownerId;
@property (nonatomic, retain) NSString * postTypeCode;
@property (nonatomic, retain) NSString * messageText;
@property (nonatomic, retain) NSDate * createdAt;
@property (nonatomic, retain) NSDate * takenAt;
@property (nonatomic, retain) NSString * accessTypeCode;
@property (nonatomic, retain) THChannel *post;
@property (nonatomic, retain) THUser *owner;

@end

AppDelegate.m

// Log all HTTP traffic with request and response bodies
RKLogConfigureByName("RestKit/Network", RKLogLevelTrace);

// Log debugging info about Core Data
RKLogConfigureByName("RestKit/CoreData", RKLogLevelDebug);
RKLogConfigureByName("RestKit/ObjectMapping", RKLogLevelTrace);

NSError *error = nil;

NSURL *baseURL = [NSURL URLWithString:API_BASE_URL];
NSIndexSet *successStatusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful); // Anything in 2xx status codes

[AFNetworkActivityIndicatorManager sharedManager].enabled = YES;

RKObjectManager *manager = [RKObjectManager managerWithBaseURL:baseURL];

// Initialize managed object store
NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];

[managedObjectStore createPersistentStoreCoordinator];
NSString *path = [RKApplicationDataDirectory() stringByAppendingPathComponent:@"MyApp.sqlite"];
NSDictionary *options = @{  NSMigratePersistentStoresAutomaticallyOption: @(NO),
                            NSInferMappingModelAutomaticallyOption: @(NO) };
NSPersistentStore *persistentStore = [managedObjectStore addSQLitePersistentStoreAtPath:path fromSeedDatabaseAtPath:nil withConfiguration:nil options:options error:&error];
if (! persistentStore) {
    RKLogError(@"Failed adding persistent store at path '%@': %@", path, error);
}

[managedObjectStore createManagedObjectContexts];

RKEntityMapping *channelEntityMapping = [RKEntityMapping mappingForEntityForName:@"THChannel" inManagedObjectStore:managedObjectStore];

channelEntityMapping.identificationAttributes = @[ @"channelId" ];
[channelEntityMapping addAttributeMappingsFromDictionary:@{ @"_id": @"channelId",
                                                            @"name": @"name",
                                                            @"desc": @"desc",
                                                            @"access": @"accessCode",
                                                            @"nmupl": @"nonMemberUploads",
                                                            @"meta.created": @"createdAt",
                                                            @"affiliation": @"viewerAffiliationCode",
                                                            @"canPost": @"viewerCanPost",
                                                            @"count.subscribers": @"countSubscribers",
                                                            @"count.comments": @"countComments",
                                                            @"count.posts": @"countPosts",
                                                            @"count.photos": @"countPhotos",
                                                            @"count.messages": @"countMessages",
                                                            @"count.joined": @"countJoined",
                                                            @"count.invited": @"countInvited" }];

RKEntityMapping *postEntityMapping = [RKEntityMapping mappingForEntityForName:@"THPost" inManagedObjectStore:managedObjectStore];

postEntityMapping.identificationAttributes = @[ @"postId" ];
[postEntityMapping addAttributeMappingsFromDictionary:@{ @"_id": @"postId",
                                                         @"channel._id": @"channelId",
                                                         @"type": @"postTypeCode",
                                                         @"message": @"messageText",
                                                         @"meta.created": @"createdAt",
                                                         @"taken": @"takenAt",
                                                         @"access": @"accessTypeCode"
                                                         }];




[channelEntityMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"member_statuses" toKeyPath:@"posts" withMapping:postEntityMapping]];

NSEntityDescription *postEntity = [NSEntityDescription entityForName:@"THPost" inManagedObjectContext:managedObjectStore.mainQueueManagedObjectContext];
 NSRelationshipDescription *postRelationship = [postEntity relationshipsByName][@"post"];
 RKConnectionDescription *connection2 = [[RKConnectionDescription alloc] initWithRelationship:postRelationship attributes:@{ @"channelId": @"channelId" }];
 [postEntityMapping addConnection:connection2];

RKResponseDescriptor *channelsOverviewObjectDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:channelEntityMapping
                                                                                              method:RKRequestMethodAny
                                                                                         pathPattern:@"/channels/:channelID"
                                                                                             keyPath:@"data.channel"
                                                                                         statusCodes:successStatusCodes];

[manager addResponseDescriptorsFromArray:@[channelsOverviewObjectDescriptor]];

// Set the default store shared instance
manager.managedObjectStore = managedObjectStore;

[RKObjectManager setSharedManager:manager];

1 个答案:

答案 0 :(得分:0)

问题在于:

[channelEntityMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"member_statuses" toKeyPath:@"posts" withMapping:postEntityMapping]];

适用于嵌套数据,而不是您拥有的数据。您有2种不同的词典,包含2种不同类型的数据。

幸运的是,member_statuses数组包含相关通道的id,因此您可以执行外键映射。您还已将频道ID映射到帖子(这是其他必需部分)。为此,您将需要2个响应描述符,这些描述符对同一响应进行操作。 1个用于频道,1个用于帖子。应该与通道建立连接的post映射(因此从通道映射中删除属性映射)。

外键映射应设置如下:

NSEntityDescription *entity = [NSEntityDescription entityForName:@"THPost" inManagedObjectContext:managedObjectContext];
NSRelationshipDescription *relationship = [entity relationshipsByName][@"post"];
RKConnectionDescription *connection = [[RKConnectionDescription alloc] initWithRelationship:e

关系属性:@ {@“channelId”:@“channelId”}];

然后将连接添加到帖子映射。