Restkit 0.20 对象在获取 json 响应后未映射

Posted

技术标签:

【中文标题】Restkit 0.20 对象在获取 json 响应后未映射【英文标题】:Restkit 0.20 objects are not mapped after getting json response 【发布时间】:2013-05-14 20:37:08 【问题描述】:

我正在使用 RestKit 0.20。我正在尝试从本地 rails 应用程序下载 json 响应并将其保存到 core-data。我尝试关注https://github.com/RestKit/RKGist/blob/master/TUTORIAL.md,一切正常。 我想多次使用它,所以我将它设为基类(ListController)并将其子类化为 SessionListController 和 EventListController。映射在 AppDelegate.m 中提供。

该应用程序有一个第一个视图控制器,它是根控制器,它始终映射响应并且一切正常。但是一旦我更改视图控制器,我就会得到响应并且操作停止。它甚至没有说映射是否已经开始。我不确定我错过了什么。

这里我正在初始化restkit

AppDelegate.m

#import "AppDelegate.h"
#import <UIKit/UIKit.h>

@implementation AppDelegate   

RKEntityMapping *eventEntityMapping,*sessionEntitiyMapping;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

NSError *error = nil;
NSURL *modelURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"event" ofType:@"momd"]];
NSManagedObjectModel *managedObjectModel = [[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL] mutableCopy];
[self setManagedObjectStore: [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel]];

// Initialize the Core Data stack
[self.managedObjectStore createPersistentStoreCoordinator];

NSPersistentStore __unused *persistentStore = [self.managedObjectStore addInMemoryPersistentStore:&error];
NSAssert(persistentStore, @"Failed to add persistent store: %@", error);

[self.managedObjectStore createManagedObjectContexts];

// Set the default store shared instance
[RKManagedObjectStore setDefaultStore:self.managedObjectStore];

NSString *url=@"http://192.168.11.11:3000";

RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:url]];
objectManager.managedObjectStore = self.managedObjectStore;

[RKObjectManager setSharedManager:objectManager];

[self mapEntities];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:eventEntityMapping pathPattern:@"/api/v1/events" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];

[objectManager addResponseDescriptor:responseDescriptor];

RKResponseDescriptor *responseDescriptor2 = [RKResponseDescriptor responseDescriptorWithMapping:sessionEntitiyMapping pathPattern:@"/api/v1/sessions" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];

[objectManager addResponseDescriptor:responseDescriptor2];


// Override point for customization after application launch.
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard_iPhone" bundle:nil];
UINavigationController *navigationController = [storyboard instantiateViewControllerWithIdentifier:@"mainCenterController"];

IIViewDeckController* secondDeckController =  [[IIViewDeckController alloc] initWithCenterViewController:navigationController
                                                                                      leftViewController:[storyboard instantiateViewControllerWithIdentifier:@"sideBarController"]];
secondDeckController.centerhiddenInteractivity=IIViewDeckCenterHiddenNotUserInteractiveWithTapToClose;
self.window.rootViewController = secondDeckController;
return YES;


-(void)mapEntities
//event
eventEntityMapping = [RKEntityMapping mappingForEntityForName:@"Event" inManagedObjectStore:self.managedObjectStore];
[eventEntityMapping addAttributeMappingsFromDictionary:@
 @"id":             @"event_id",
 @"name":           @"name",
 @"description":    @"desc",
 @"no_of_days":     @"no_of_days",
 @"start_date":     @"start_date",
 ];
eventEntityMapping.identificationAttributes = @[ @"event_id" ];

sessionEntitiyMapping = [RKEntityMapping mappingForEntityForName:@"Session" inManagedObjectStore:self.managedObjectStore];
[sessionEntitiyMapping addAttributeMappingsFromDictionary:@
 @"name":           @"name",
 @"description":    @"desc",
 @"start_time":     @"start_time",
 @"duration":       @"duration",
 @"location_id":    @"location_id",
 @"event_id":       @"event_id",
 @"id":             @"session_id",
 ];
sessionEntitiyMapping.identificationAttributes = @[ @"session_id" ];

我根据基类为 RKManager 调用 getObjectsAtPath 的基类。

ListController.m

@implementation ListController
- (void)viewDidLoad

[super viewDidLoad];
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
self.managedObjectContext = appDelegate.managedObjectStore.mainQueueManagedObjectContext;
[self loadLocs];
[self.refreshControl beginRefreshing];


-(void)setModel:(Models)model
if(self.model!=model)
    _model=model;
    self.title=[Model displayFor:self.model];
    _fetchedResultsController = nil;
    [self.tableView reloadData];
    [self loadLocs];
    [self.refreshControl beginRefreshing];



- (void)loadLocs

[[RKObjectManager sharedManager] getObjectsAtPath:[Model listApiFor:self.model]
                                       parameters:nil
                                          success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) 
                                              [self.refreshControl endRefreshing];
                                          
                                          failure:^(RKObjectRequestOperation *operation, NSError *error) 
                                              [self.refreshControl endRefreshing];
                                              UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"An Error Has Occurred" message:[error localizedDescription] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
                                              NSLog(@"error: %@",error);
                                              [alertView show];
                                          ];



#pragma mark - Table View

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

return [[[self fetchedRCforTableView:tableView] sections] count];


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section];
return [sectionInfo numberOfObjects];


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
[self configureCell:cell atIndexPath:indexPath forTableView:tableView];
return cell;


#pragma mark - Fetched results controller
- (NSFetchedResultsController *)fetchedResultsController

if (_fetchedResultsController != nil) 
    return _fetchedResultsController;


NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:[Model entityFor:self.model] inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];

// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];

// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:[Model sortDescriptorFor:self.model] ascending:YES];
NSArray *sortDescriptors = @[sortDescriptor];

[fetchRequest setSortDescriptors:sortDescriptors];

NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:[Model displayFor:self.model]];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;

NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) 
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();

NSLog(@"_fetchedResultsController count %d",_fetchedResultsController.fetchedObjects.count);
return _fetchedResultsController;


@end

这是我设置模型名称的基类之一

EventViewController.m

- (void)viewDidLoad

[super viewDidLoad];
self.model=Eventm;
// Do any additional setup after loading the view.

SessionViewController.m

- (void)viewDidLoad

[super viewDidLoad];
self.model=Sessionm;
// Do any additional setup after loading the view.

完整代码在https://github.com/leohemanth/event-app

使用后

RKLogConfigureByName("RestKit", RKLogLevelWarning);
RKLogConfigureByName("RestKit/ObjectMapping", RKLogLevelTrace);
RKLogConfigureByName("RestKit/Network", RKLogLevelTrace);

我可以看到,我得到了正确的 Http 响应,但它没有被映射。我不知道为什么?

【问题讨论】:

日志是不是说有时候找不到响应描述符?或者没有键路径匹配?需要一些日志才能继续或对 JSON 进行采样以进行比较。 没有日志没有任何错误信息。它只是在记录响应文本后停止。事件的示例 json 响应是 gist.github.com/leohemanth/5579457 listApiFor 的代码是什么: - 它返回什么路径? listApiFor 返回事件的 api 路径 - return @"/api/v1/events" 和会话 return @"/api/v1/sessions"我> 定义响应描述符时,指定不带前导“/”的路径模式。使用跟踪登录时您没有得到任何日志信息似乎很奇怪,通常它会告诉您问题的确切位置。 【参考方案1】:

我刚刚将我的 Restkit 包更新到 0.20.2。我现在没有面临这个问题。它应该在更新中修复。

【讨论】:

以上是关于Restkit 0.20 对象在获取 json 响应后未映射的主要内容,如果未能解决你的问题,请参考以下文章

Restkit 0.20 JSON 映射以及额外的离线数据

Restkit 0.20 JSON 映射以及额外的离线数据

Restkit 0.20 嵌套对象数组映射问题

使用 RESTKIT 0.20 映射未命名值的 JSON 数组

使用 RestKit 0.20 映射时在 JSON 中向上遍历

RestKit 0.20 with Core Data:删除对象