At the moment I'm struggling with the deletion of Orphaned objects.
I've the following classes.
MAPPER CLASS
In this class I create all my RKObjectManagers and use it in my other classes.
-(RKObjectManager *)mapAppointments{
RKEntityMapping* appointmentMapping = [RKEntityMapping mappingForEntityForName:#"Appointment" inManagedObjectStore:managedObjectStore];
appointmentMapping.identificationAttributes = #[#"app_id",#"app_start"] ;
[appointmentMapping addAttributeMappingsFromDictionary:#{
#"AddressInfo": #"app_addressinfo",
#"Completed": #"app_completed",
#"Description": #"app_description",
#"EndDate":#"app_end",
#"FullDay": #"app_fullday",
#"Id":#"app_id",
#"Label": #"app_label",
#"LabelId": #"app_label_id",
#"Location": #"app_location",
#"Private":#"app_private",
#"ProjectName":#"app_project_name",
#"ProjectNumber": #"app_project_number",
#"RecurrenceInfo": #"app_recurrenceInfo",
#"RelationAddressCity": #"app_relation_address_city",
#"RelationAddressId":#"app_relation_address_id",
#"RelationAddressName": #"app_relation_address_name",
#"RelationAddressStreet":#"app_relation_address_street",
#"RelationCode": #"app_relation_code",
#"RelationContactPersonId": #"app_relation_contact_id",
#"RelationContactPersonName": #"app_relation_contact_name",
#"RelationName":#"app_relation_name",
#"ReminderInfo":#"app_reminder_info",
#"StartDate": #"app_start",
#"State": #"app_state",
#"Subject": #"app_subject",
#"SupplierCode":#"app_supplier_code",
#"SupplierContactPersonId": #"app_supplier_contact_person_id",
#"SupplierContactPersonName":#"app_supplier_contact_person_name",
#"SupplierName": #"app_supplier_name",
#"Type": #"app_type",
#"ResxPers":#"app_resxPers",
}];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:appointmentMapping pathPattern:nil keyPath:#"" statusCodes:[NSIndexSet indexSetWithIndex:200]];
NSArray *arrResponsDescriptor = [[NSArray alloc]initWithObjects:responseDescriptor,nil];
[objectManager addResponseDescriptorsFromArray:arrResponsDescriptor];
return objectManager;
}
WEBSERVICE CLASS
In this class I do my request and also try to delete the Orphaned objects.
-(void)fetchAppointmentsOnCompletionFor:(NSDate *)start andEnd:(NSDate *)end OnCompletion:(myCompletion) compblock{
Mapper *mapper = [Mapper new];
RKManagedObjectStore *store = [[AdsolutDataModel sharedDataModel] objectStore];
NSLog(#"store is %#",store);
NSManagedObjectContext *context = store.mainQueueManagedObjectContext;
RKObjectManager *objectManager = [mapper mapAppointments];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setTimeZone:[NSTimeZone defaultTimeZone]];
[dateFormatter setDateFormat:#"dd-MM-yyyy"];
NSString *strStart = [dateFormatter stringFromDate:start];
NSString *strEnd = [dateFormatter stringFromDate:end];
NSString *userName = [[NSUserDefaults standardUserDefaults]valueForKey:#"userName"];
NSString *hash = [[NSUserDefaults standardUserDefaults]valueForKey:#"hash"];
NSString *urlString = [NSString stringWithFormat:#"getcrmappointments?gebrcode=%#&token=%#&startdate=%#&enddate=%#",userName,hash,strStart,strEnd];
[objectManager addFetchRequestBlock:^NSFetchRequest *(NSURL *URL) {
RKPathMatcher *pathMatcher = [RKPathMatcher pathMatcherWithPattern:urlString];
NSDictionary *argsDict = nil;
BOOL match = [pathMatcher matchesPath:[URL relativePath] tokenizeQueryStrings:NO parsedArguments:&argsDict];
if (match) {
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"Appointment"];
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"(app_start >= %#) AND (app_end <= %#)", start,end]; // NOTE: Coerced from string to number
fetchRequest.sortDescriptors = #[ [NSSortDescriptor sortDescriptorWithKey:#"app_id" ascending:YES] ];
return fetchRequest;
}
return nil;
}];
NSURLRequest *request = [objectManager requestWithObject:nil method:RKRequestMethodGET path:urlString parameters:nil];
RKManagedObjectRequestOperation *operation = [objectManager managedObjectRequestOperationWithRequest:request managedObjectContext:context success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(#"REQUEST URL = %#",request.URL);
NSError *error = nil;
BOOL success = [context save:&error];
if (!success) RKLogWarning(#"Failed saving managed object context: %#", error);
NSLog(#"SUCCESS");
NSError *saveError = nil;
for (Appointment *appointment in mappingResult.array) {
NSLog(#"Appointment title is %#",appointment.app_subject);
appointment.synchronized = #1;
appointment.app_delete = #0;
[context saveToPersistentStore:&saveError];
}
[self fetchAfwezighedenOnCompletionFor:start andEnd:end OnCompletion:^(BOOL finished) {
if(finished){
compblock(YES);
}
}];
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error"
message:[error localizedDescription]
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
NSLog(#"Hit error: %#", error);
}];
[objectManager enqueueObjectRequestOperation:operation];
}
PROBLEM
At the moment, the Orphaned objects are not deleted. Am I doing somehting wrong or is something not setup right ?
Thanks for the help !
Looking at the code for RKObjectManager managedObjectRequestOperationWithRequest: shows that the fetch request blocks are passed from the object manager passed to the operation. So, debugging would be required to work out why it wasn't called. It should be called in all 'success' scenarios (i.e. ones where a response descriptor matches the received response).
You could look at using the manager to make the request instead of getting a request and using RKManagedObjectRequestOperation, but in theory this should simply be less code to write rather than a functional difference.
Try changing the fetch request block:
RKPathMatcher *pathMatcher = [RKPathMatcher pathMatcherWithPattern:#"getcrmappointments"];
Related
Possible duplication : RestKit Core Data 'managedObjectStore is nil'
Could somebody explain me why when I run my application I get error like :
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: managedObjectStore'
*** First throw call stack
It happened to me only in my MainViewController when I'm calling the following method:
-(void)loadLocationsOfWearers{
RKManagedObjectStore *store = [[DateModel sharedDataModel] objectStore];
NSIndexSet *statusCodeSet= RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
RKMapping *mapping = [MappingProvider watchesMapping];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping method:RKRequestMethodAny pathPattern:nil keyPath:#"watch" statusCodes:statusCodeSet];
NSURL *url = [NSURL URLWithString:kSERVER_ADDR];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
RKManagedObjectRequestOperation *operation =[[RKManagedObjectRequestOperation alloc] initWithRequest:request responseDescriptors:#[responseDescriptor]];
operation.managedObjectCache = store.managedObjectCache;
operation.managedObjectContext = store.mainQueueManagedObjectContext;
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
_wearerList = mappingResult.array;
NSLog(#"Results:\n %#",mappingResult.dictionary);
}
failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"ERROR: %#", error);
NSLog(#"Response: %#", operation.HTTPRequestOperation.responseString);
}];
[operation start];
}
When I'm calling this method in other ViewControllers everything works fine.
It looks like my managedObjectStore is nil, but I don't know what is the reason for that...
Please take a look at my DateModel code and share with me your ideas:
#implementation DateModel
+ (id)sharedDataModel
{
static DateModel *__sharedDataModel = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
__sharedDataModel = [[DateModel alloc] init];
});
return __sharedDataModel;
}
- (NSManagedObjectModel *)managedObjectModel
{
return [NSManagedObjectModel mergedModelFromBundles:nil];
}
- (id)optionsForSqliteStore
{
return #{
NSInferMappingModelAutomaticallyOption: #YES,
NSMigratePersistentStoresAutomaticallyOption: #YES
};
}
- (void)setup
{
self.objectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSString *path = [RKApplicationDataDirectory() stringByAppendingPathComponent:#"Data.sqlite"];
NSLog(#"Setting up store at %#", path);
NSError *error;
[self.objectStore addSQLitePersistentStoreAtPath:path
fromSeedDatabaseAtPath:nil
withConfiguration:nil
options:[self optionsForSqliteStore]
error:&error];
[self.objectStore createManagedObjectContexts];
self.objectStore.managedObjectCache =[[RKInMemoryManagedObjectCache alloc]initWithManagedObjectContext:self.objectStore.persistentStoreManagedObjectContext];
[RKManagedObjectStore setDefaultStore:self.objectStore];
}
In my AppDelegate method I just simply setup my store.
-(void)setupCoreData
{
[[DateModel sharedDataModel]setup];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self setupCoreData];
}
When I run my application I'm getting error like on the screen below:
+(RKMapping *)watchesMapping
{
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:#"Watches" inManagedObjectStore:[[DateModel sharedDataModel]objectStore]];
[mapping addAttributeMappingsFromDictionary:#{
#"id": #"watch_id",
#"altitude":#"altitude",
#"battery_life":#"battery_life",
#"button_press_time":#"button_press_time",
#"charging_status":#"charging_status",
#"gmaps":#"gmaps",
#"id_addr":#"id_addr",
#"last_keep_alive":#"last_keep_alive",
#"last_update_time":#"last_update_time",
#"latitude":#"latitude",
#"longitude":#"longitude",
#"location":#"location",
#"network":#"network",
#"phonewatchno":#"phonewatchno",
#"rssi":#"rssi",
#"short_imei":#"short_imei",
#"updated_at":#"updated_at",
#"voltage":#"voltage",
#"waerer_id":#"wearer_id",
#"updated_at":#"updated_at",
#"token":#"token"
}
];
[mapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"alerts" toKeyPath:#"alerts" withMapping:[MappingProvider alertsMapping]]];
return mapping;
}
loadLocationsOfWearers is being called too soon (before setupCoreData is called). Call it later, or call setupCoreData when the data model singleton is created.
I'm working on RestKit to store data in Core Data I have done storing them on transient objects. How do I save them parallely in Core Data.
Should I assign PersistentStore to RKObjectManager or NSManagedObjectContext to RKObjectManager.
I have gone through many tutorials each one conflicts from other.
Suggest some clear Tutorial to work on.
After going through github tutorial i have written the following code for mapping data to coredata and transient objects.But it is not working
//assigning the model
NSURL *modelURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"Sample" ofType:#"momd"]];
NSLog(#"sql:%#",[RKApplicationDataDirectory() stringByAppendingPathComponent:#"Sample![enter image description here][1].sqlite"]);
objectManager=[[RKObjectManager alloc]init];
// NOTE: Due to an iOS 5 bug, the managed object model returned is immutable.
NSManagedObjectModel *managedObjectModel = [[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL] mutableCopy];
managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
objectManager.managedObjectStore = managedObjectStore;
NSError *error;
[managedObjectStore addSQLitePersistentStoreAtPath:[RKApplicationDataDirectory() stringByAppendingPathComponent:#"FourthEstateApp.sqlite"] fromSeedDatabaseAtPath:nil withConfiguration:nil options:nil error:&error];
NSLog(#"sql:%#",[RKApplicationDataDirectory() stringByAppendingPathComponent:#"FourthEstateApp.sqlite"]);
[managedObjectStore createManagedObjectContexts];
//creating mapping
storyDataMapping=[RKEntityMapping mappingForEntityForName:#"Story" inManagedObjectStore:managedObjectStore];
[storyDataMapping addAttributeMappingsFromArray:[NSArray arrayWithObjects:
#"shares",
#"views",
#"weight",
#"story_url",
#"other_articles",
#"color",
#"public_url",
#"images_urls", nil
]
];
articleDataMapping=[RKEntityMapping mappingForEntityForName:#"Article" inManagedObjectStore:managedObjectStore];
[articleDataMapping addAttributeMappingsFromArray:[
NSArray arrayWithObjects:#"location", #"original_url",
#"publication_date_time", #"title",
#"article_url", #"source_name",
#"source_twitter_id", nil
]
];
[storyDataMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"main_article"
t toKeyPath:#"main_article"
withMapping:articleDataMapping]];
responseDescriptorForStoryData = [RKResponseDescriptor responseDescriptorWithMapping:storyDataMapping method:RKRequestMethodGET
pathPattern:Nil keyPath:nil statusCodes:
RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptorsFromArray:#[responseDescriptorForStoryData]];
NSURL *URL = [NSURL URLWithString:categoryURL];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
RKManagedObjectRequestOperation *objectRequestOperation = [[RKManagedObjectRequestOperation alloc] initWithRequest:request
responseDescriptors:#[responseDescriptorForStoryData]];
[objectRequestOperation
setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(#"Load collection of Articles: %#", mappingResult);
for (Story *s in mappingResult.array) {
NSLog(#"storymain article is:%#", s.main_article.title);
[stories addObject:s];
}
//on success fetching the data from coredata
NSManagedObjectContext *managedObjectContext =[[NSManagedObjectContext alloc]init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Story" inManagedObjectContext:managedObjectStore.mainQueueManagedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
// Execute the fetch -- create a mutable copy of the result.
NSError *error = nil;
NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
NSLog(#"results from cd:%# error:%#",mutableFetchResults,error);
[[NSNotificationCenter defaultCenter] postNotificationName:#"success" object:stories];
}
failure:^(RKObjectRequestOperation *operation, NSError *error) {
//RKLogError(#"Operation failed with error: %#", error);
[[NSNotificationCenter defaultCenter] postNotificationName:#"failure" object:error];
NSLog(#"Operation failed with error: %#", error);
}
];
Enter code here
[objectManager enqueueObjectRequestOperation:objectRequestOperation];
[objectRequestOperation start];
successblock is executed
when I am trying to fetch the data following error is occured
CoreData: error: Failed to call designated initializer on NSManagedObject class 'Story'
I just found out RestKit and it will be an important part of the app I'm doing. At the time, I was able to integrate it with the core data, but have not figured out the best way to send multiple GET requests.
What I need to do is:
Get data from the following addresses:
http://url.com/api/banner/
http://url.com/api/category/
http://url.com/api/link/
The URL will always be in the following format: http://url.com/api/SOMETHING/
Once all requests are finished, I would like to run a code (such as calling a new view controller). What would be the best way to do this?
At the moment, this is the code I'm using:
- (id)init
{
self = [super init];
if (self) {
[self setupConnector];
[self setupDatabase];
[self setupMappings];
[self sendRequests];
}
return self;
}
- (void)setupConnector
{
// Initialize RestKIT
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:#"http://baseURL"]];
self.managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:[[NLCoreData shared] managedObjectModel]];
objectManager.managedObjectStore = self.managedObjectStore;
}
- (void)setupDatabase
{
NSString *storePath = [[NLCoreData shared] storePath];
NSError *error = nil;
NSPersistentStore *persistentStore = [self.managedObjectStore addSQLitePersistentStoreAtPath:storePath fromSeedDatabaseAtPath:nil withConfiguration:nil options:nil error:&error];
NSAssert(persistentStore, #"Failed to add persistent store with error: %#", error);
[self.managedObjectStore createManagedObjectContexts];
self.managedObjectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:self.managedObjectStore.persistentStoreManagedObjectContext];
}
- (void)setupMappings
{
RKObjectManager *objectManager = [RKObjectManager sharedManager];
// Mappings
// banner
RKEntityMapping *bannerMapping = [RKEntityMapping mappingForEntityForName:#"Banner" inManagedObjectStore:self.managedObjectStore];
[bannerMapping addAttributeMappingsFromDictionary:#{
#"title": #"title",
#"id": #"bannerID",
#"created_at": #"created_at",
#"image": #"image",
#"resource_uri": #"resource_uri",
#"updated_at": #"updated_at",
#"url": #"url"
}];
bannerMapping.identificationAttributes = #[ #"bannerID" ];
RKResponseDescriptor *bannerDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:bannerMapping
pathPattern:#"/api/v1/banner/"
keyPath:#"objects"
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:bannerDescriptor];
// category
RKEntityMapping *categoryMapping = [RKEntityMapping mappingForEntityForName:#"Category" inManagedObjectStore:self.managedObjectStore];
[categoryMapping addAttributeMappingsFromDictionary:#{
#"name": #"name",
#"id": #"categoryID",
#"created_at": #"created_at",
#"resource_uri": #"resource_uri",
#"updated_at": #"updated_at",
#"active": #"active"
}];
categoryMapping.identificationAttributes = #[ #"categoryID" ];
RKResponseDescriptor *categoryDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:categoryMapping
pathPattern:#"/api/v1/category/"
keyPath:#"objects"
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:categoryDescriptor];
}
- (void)sendRequests
{
RKObjectManager *objectManager = [RKObjectManager sharedManager];
// Send Request
[objectManager getObjectsAtPath:#"/api/v1/banner/" parameters:nil success:^(RKObjectRequestOperation * operation, RKMappingResult *mappingResult) {
NSLog(#"SUCCESS: %#", mappingResult.array);
} failure: ^(RKObjectRequestOperation * operation, NSError * error) {
NSLog(#"FAILURE %#", error);
}];
// category
[objectManager getObjectsAtPath:#"/api/v1/category/" parameters:nil success:^(RKObjectRequestOperation * operation, RKMappingResult *mappingResult) {
NSLog(#"SUCCESS: %#", mappingResult.array);
} failure: ^(RKObjectRequestOperation * operation, NSError * error) {
NSLog(#"FAILURE %#", error);
}];
}
Any tips?
The RestKit solution would be this: instead of using the convenience method ObjectManager::getObjectsAtPath you will have to init all of your RKObjectRequestOperations manually and then use ObjectManager::enqueueBatchOfObjectRequestOperations:progress:completion: method to enqueue them.
Alternatively, and I think this is actually easier and cleaner solution, use dispatch groups as described in the accepted answer to this question.
NSURL *url1 = [NSURL URLWithString:#"http://baseURL.domain/api/banner/"];
NSMutableURLRequest *request2 = [NSMutableURLRequest requestWithURL:url1];
RKObjectRequestOperation *objectRequestOperation1 = [[RKObjectRequestOperation alloc] initWithRequest:request2 responseDescriptors:#[ ResponseDescriptor ]];
NSURL *url2 = [NSURL URLWithString:#"http://baseURL.domain/api/category/"];
NSMutableURLRequest *request2 = [NSMutableURLRequest requestWithURL:url2];
RKObjectRequestOperation *objectRequestOperation2 = [[RKObjectRequestOperation alloc] initWithRequest:request2 responseDescriptors:#[ ResponseDescriptor ]];
NSArray *requestArray = [NSArray arrayWithObjects:objectRequestOperation,objectRequestOperation1,objectRequestOperation2, nil];
[[RKObjectManager sharedManager] enqueueBatchOfObjectRequestOperations:requestArray progress:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) {
//
// Handle process indicator
//
NSLog(#"%lu",(unsigned long)totalNumberOfOperations);
} completion:^(NSArray *operations) {
//
// Remove blocking dialog, do next tasks
?
So I am trying to grab information in JSON from my rails app with RestKit
My code to do so is like so:
App Delegate
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//Initialise RestKit
NSURL *URL = [NSURL URLWithString:#"https://myapp.dev"];
AFHTTPClient* client = [[AFHTTPClient alloc] initWithBaseURL:URL];
//Enable Activity Indicator Spinner
[AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
[client setDefaultHeader:#"Accept" value:RKMIMETypeJSON];
RKObjectManager *objectManager = [[RKObjectManager alloc] initWithHTTPClient:client];
RKObjectMapping *eventMapping = [RKObjectMapping mappingForClass:[Info class]];
[infoMapping addAttributeMappingsFromDictionary:#{
#"sample":#"sample",
#"sample_1":#"sample_1"
}];
RKResponseDescriptor *infoDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:infoMapping
pathPattern:#"/info"
keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:infoDescriptor];
}
View File
- (void)loadInfo
{
RKObjectManager *objectManager = [RKObjectManager sharedManager];
[objectManager getObjectsAtPath:#"/info"
parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSArray *info = [mappingResult array];
NSLog(#"Loaded info: %#", info);
_info = info;
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error getting into"
message:[error localizedDescription]
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
NSLog(#"Hit error: %#", error);
}];
}
The problem is. On the log output, RestKit tells me it maps everything successfully. But then when I attempt to view the object with both the method to log in the view file and with the debugger using po I get the following
374 Finished performing object mapping. Results: {
"<null>" = "<Info: 0xa291b30>";
}
I can't view the object and with breakpoints it shows up as:
I've been struggling with this for a few days and I'm not sure what else to try. Any help would be greatly appreciated
I ran into a similar problem. I'm not too sure why, but when I did the following it fixed it.
- (void)loadInfo
{
RKObjectManager *objectManager = [RKObjectManager sharedManager];
[objectManager getObjectsAtPath:#"/info"
parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSArray *info = [mappingResult array];
NSLog(#"Loaded info: %#", info);
_info = info;
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error getting into"
message:[error localizedDescription]
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
NSLog(#"Hit error: %#", error);
}];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//Initialise RestKit
NSURL *URL = [NSURL URLWithString:#"https://myapp.dev"];
AFHTTPClient* client = [[AFHTTPClient alloc] initWithBaseURL:URL];
//Enable Activity Indicator Spinner
[AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
[client setDefaultHeader:#"Accept" value:RKMIMETypeJSON];
RKObjectManager *objectManager = [[RKObjectManager alloc] initWithHTTPClient:client];
RKObjectMapping *eventMapping = [RKObjectMapping mappingForClass:[Info class]];
[infoMapping addAttributeMappingsFromDictionary:#{
#"sample":#"sample",
#"sample_1":#"sample_1"
}];
RKResponseDescriptor *infoDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:infoMapping
pathPattern:#"/info/:id"
keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:infoDescriptor];
}
When you load an object representation that does not have a nesting keyPath, RestKit stores the mapped objects under the [NSNull null] key within the dictionary (since nil is not a valid dictionary key). You can retrieve the mapping results either by calling firstObject, array, or dictionary on the RKMappingResult object to access the mapped objects.
I see a follow-up question about mapping an array to a single object... what does your JSON look like and how are you trying to represent it?
RKResponseDescriptor *infoDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:infoMapping
pathPattern:nil
keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
I installed RestKit (0.20.0-pre3) via CocoaPods and configured it as the documentation states it. When performing the getObjectsAtPath and RestKit does the mapping I get:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSManagedObjectContext saveToPersistentStore:]: unrecognized selector sent to instance 0x9eaae40'
If I set a breakpoint it stops at RKManagedObjectRequestOperation.m at line 278.
I configured RestKit as follows:
- (void)configureRestKit{
//initialize RestKit
LLog(DEBUG_LEVEL, #"init RestKit");
NSString *baseURL;
// Log all HTTP traffic with request and response bodies
//RKLogConfigureByName("RestKit/Network", RKLogLevelTrace);
// Log debugging info about Core Data
RKLogConfigureByName("RestKit/CoreData", RKLogLevelTrace);
//Loging about the Entity Mapping
RKLogConfigureByName("RestKit/ObjectMapping", RKLogLevelTrace)
// enable activity indicator
[AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
if (local) {
baseURL = #"http://xyz.net";
} else {
baseURL = #"http://XYZ.net";
}
[RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:#"application/json"];
_objectManager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:baseURL]];
_managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
_managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:_managedObjectModel];
NSString *path = [RKApplicationDataDirectory() stringByAppendingPathComponent:#"XYZ.sqlite"];
//LLog(DEBUG_MODE,#"The object store: %#", _objectStore.description);
[_managedObjectStore addSQLitePersistentStoreAtPath:path fromSeedDatabaseAtPath:nil withConfiguration:nil options:nil error:nil];
[_managedObjectStore createManagedObjectContexts];
[_managedObjectStore createPersistentStoreCoordinator];
_managedObjectContext = _managedObjectStore.persistentStoreManagedObjectContext;
_persistentStoreCoordinator = _managedObjectStore.persistentStoreCoordinator;
_managedObjectModel = _managedObjectStore.managedObjectModel;
_objectManager.managedObjectStore = _managedObjectStore;
// 2012-06-13T00:00:00+01:00
NSDateFormatter *dateFormatter = [NSDateFormatter new];
[dateFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss'+01:00'"];
dateFormatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:#"UTC"];
dateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"];
// Set it Globally
[RKObjectMapping setPreferredDateFormatter:dateFormatter];
LLog(DEBUG_LEVEL, #"DateFormater Test: %#", [dateFormatter stringFromDate:[NSDate date]]);
// Add Entity Mapping
RKEntityMapping *experienceMapping = [RKEntityMapping mappingForEntityForName:#"Experience" inManagedObjectStore:_managedObjectStore];
[experienceMapping addAttributeMappingsFromArray:#[#"experienceid", #"city", #"descr", #"lat", #"lng", #"number", #"price", #"street"]];
experienceMapping.identificationAttributes = #[#"experienceid"];
NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful); // Anything in 2xx
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:experienceMapping pathPattern:#"/test.json" keyPath:#"experience" statusCodes:statusCodes];
[_objectManager addResponseDescriptor:responseDescriptor];
// ###### ONLY FOR TEST REASONS ######
NSManagedObject *test = [NSEntityDescription
insertNewObjectForEntityForName:#"Experience"
inManagedObjectContext:_managedObjectContext];
[test setValue:[NSNumber numberWithInt:1] forKey:#"experienceid"];
[test setValue:#"Testville" forKey:#"city"];
NSError *error;
if (![_managedObjectContext save:&error]) {
NSLog(#"Whoops, couldn't save: %#", [error localizedDescription]);
}
[_objectManager getObjectsAtPath:#"/test.json" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
// Handled with articleDescriptor
LLog(DEBUG_LEVEL, #"Test");
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
// Transport error or server error handled by errorDescriptor
}];
}
Thanks for your help!
This most likely indicates that your linker flags are not set up properly. The -ObjC linker flag is required to get category methods loaded. Have you overridden the Linker Flags on your target? You need to at least include $(inherited) if you have additional configuration on the target level. You should see -ObjC appear within your linker flags when viewing the setting in Xcode.