Question

I'm using RestKit 0.20. I'm trying to download the json response from the local rails application and save it to core-data. I tried to follow https://github.com/RestKit/RKGist/blob/master/TUTORIAL.md and everything worked fine.
I wanted to use this many times so i made it a base class(ListController) and subclassed it to SessionListController and EventListController. The mapping is provided in AppDelegate.m.

The app has a first viewcontroller which is the root controller which always maps the responses and everything works fine. But as soon as i change the viewcontroller i will get the response and the operation stops. it does't even say if the mapping has started. I'm not sure what i have missed.

Here i'm initialising 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" ];
}

Base class where i'm calling getObjectsAtPath for RKManager depending on the base class.

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

This is one of the base classes where i set the model name

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.
}

Full code is at https://github.com/leohemanth/event-app

After using

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

I can see that, i'm getting proper Http response but it is not being mapped. Which i'm not sure why?

Was it helpful?

Solution

I've just updated my Restkit package to 0.20.2. I'm not facing the problem now. It should be fixed in the update.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top