So this is the first time i'm trying to map objects into CoreData, I think I got it right, but I have few issues. First of all, I just don't know if I'm mapping it the right way and the second one is that I get a success response but without objects mapped.
I have 2 objects DbRestError & DbRestCategory. DbRestError contain the error from the server and DbRestCategory contain the category itself. the are both coming back from the same response but RestKit seems unable to map them.
Those are the objects:
DbRestError
#interface DbRestError : NSManagedObject
#property (nonatomic, retain) NSNumber * statusCode;
#property (nonatomic, retain) NSString * errorTitle;
#end
DbRestCategory
#interface DbRestCategory : NSManagedObject
#property (nonatomic, retain) NSString * title;
#property (nonatomic, retain) NSNumber * idNum;
#end
This is how I initialize my CoreData with RestKit:
- (void)setup
{
self.objectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSString *path = [RKApplicationDataDirectory() stringByAppendingPathComponent:#"database.sqlite"];
NSLog(#"Setting up store at %#", path);
[self.objectStore addSQLitePersistentStoreAtPath:path
fromSeedDatabaseAtPath:nil
withConfiguration:nil
options:#{ NSInferMappingModelAutomaticallyOption: #YES, NSMigratePersistentStoresAutomaticallyOption: #YES }
error:nil];
[self.objectStore createManagedObjectContexts];
}
This is how I initialize my RestKit client:
- (void)initRestClient
{
NSURL *baseURL = [NSURL URLWithString:kWebServiceBaseURL];
self.manager = [RKObjectManager managerWithBaseURL:baseURL];
[self.manager setRequestSerializationMIMEType:RKMIMETypeJSON];
[self.manager setAcceptHeaderWithMIMEType:RKMIMETypeJSON];
[self.manager addResponseDescriptorsFromArray:[RKObjectManager sharedManager].responseDescriptors];
[self.manager addRequestDescriptorsFromArray:[RKObjectManager sharedManager].requestDescriptors];
[self.manager.HTTPClient.operationQueue setMaxConcurrentOperationCount:MAX_CONCURRENT_OPERATION_COUNT];
[self.manager setManagedObjectStore:[[MainDb sharedDb] objectStore]];
[RKObjectManager setSharedManager:self.manager];
self.requestMethod = RKRequestMethodGET;
self.statusCode = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
RKRoute *categoriesRoute = [RKRoute routeWithClass:[DbRestCategory class] pathPattern:kGetCategories method:self.requestMethod];
categoriesRoute.shouldEscapePath = YES;
[self.manager.router.routeSet addRoute:categoriesRoute];
// ##yosi -- Error Mapping
//
//
RKEntityMapping *errorMapping = [RKEntityMapping mappingForEntityForName:#"DbRestError" inManagedObjectStore:[[MainDb sharedDb] objectStore]];
[errorMapping addAttributeMappingsFromDictionary:#{ #"statusCode" : #"statusCode", #"description" : #"errorTitle" }];
// ##yosi -- Categories Mapping
//
//
RKEntityMapping *categoryMapping = [RKEntityMapping mappingForEntityForName:#"DbRestCategory" inManagedObjectStore:[[MainDb sharedDb] objectStore]];
[categoryMapping addAttributeMappingsFromDictionary:#{ #"id" : #"idNum", #"name" : #"title" }];
RKObjectMapping *categoriesMapping = [RKObjectMapping mappingForClass:[RestCategories class]];
[categoriesMapping addRelationshipMappingWithSourceKeyPath:#"categories" mapping:categoryMapping];
[categoriesMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"error" toKeyPath:#"error" withMapping:errorMapping]];
[[RKObjectManager sharedManager] addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:categoriesMapping
method:self.requestMethod
pathPattern:kGetCategories
keyPath:nil
statusCodes:self.statusCode]];
}
This is how I'm doing the request itself:
[[RKObjectManager sharedManager] getObject:[[DbRestCategory alloc] init] path:nil parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
}];
This is how the JSON looks like:
{
error: {
statusCode: 10,
description: "success"
},
categories: [
{
id: "3",
name: "cate 3"
},
{
id: "4",
name: "cate 4"
},
{
id: "5",
name: "cate 5"
},
{
id: "1",
name: "cate 1"
},
{
id: "6",
name: "cate 6"
},
{
id: "2",
name: "cate 2"
}
]
}
Can someone please help me to understand why i'm getting a response without any objects?
Try the request mapping like this,
// Request Mapping
// Map error
RKEntityMapping *errorMapping = [RKEntityMapping mappingForEntityForName:#"DbRestError" inManagedObjectStore:[[MainDb sharedDb] objectStore]];
[errorMapping addAttributeMappingsFromDictionary:#{ #"statusCode" : #"statusCode", #"description" : #"errorTitle" }];
[[RKObjectManager sharedManager] addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:errorMapping method:self.requestMethod pathPattern:kGetCategories keyPath:#"error" statusCodes:self.statusCode]];
// Map Category
RKEntityMapping *categoryMapping = [RKEntityMapping mappingForEntityForName:#"DbRestCategory" inManagedObjectStore:[[MainDb sharedDb] objectStore]];
[categoryMapping addAttributeMappingsFromDictionary:#{ #"id" : #"idNum", #"name" : #"title" }];
[[RKObjectManager sharedManager] addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:categoriesMapping method:self.requestMethod pathPattern:kGetCategories keyPath:#"categories" statusCodes:self.statusCode]];
Related
I would like to use RestKit but I don't see how to write the pathPattern and the keyPath, where the json returns :
{
"photos": {
"page": 1,
"pages": 39594,
"perpage": 10,
"total": "395933",
"photo": [
{
"id": "16766829152",
"owner": "32546988#N00",
"secret": "5b38b40c57",
"server": "8744",
"farm": 9,
"title": "City box lights",
"ispublic": 1,
"isfriend": 0,
"isfamily": 0
}
]
}
}
The error :
Error Domain=org.restkit.RestKit.ErrorDomain Code=1001 "No mappable object representations were found at the key paths searched
This is what I have now :
#define kBaseRESTURL #"https://api.flickr.com/services/rest/?method="
#define kSearchMethod #"flickr.photos.search"
-(void)configureRestKit{
NSString *url = [NSString stringWithFormat:#"%#%#", kBaseRESTURL, kSearchMethod];
NSURL *baseURL = [NSURL URLWithString:url];
AFHTTPClient* client = [[AFHTTPClient alloc] initWithBaseURL:baseURL];
RKObjectManager *manager = [[RKObjectManager alloc] initWithHTTPClient:client];
RKObjectMapping* photoMapping = [RKObjectMapping mappingForClass:[Photo class]];
[photoMapping addAttributeMappingsFromArray:#[#"title"]];
RKResponseDescriptor *responseDesc = [RKResponseDescriptor responseDescriptorWithMapping:photoMapping method:RKRequestMethodGET pathPattern:#"" keyPath:#"photos.photo" statusCodes:[NSIndexSet indexSetWithIndex:200]];
[manager addResponseDescriptor:responseDesc];
}
-(void)loadCities : (void(^)(NSArray*))completion {
[self configureRestKit];
NSDictionary *queryParams = #{#"api_key" : apiKey,
#"tags" : #"cities",
#"per_page" : #"10",
#"format" : #"json",
#"nojsoncallback" : #"1"
};
[[RKObjectManager sharedManager] getObjectsAtPath:#"" parameters:queryParams success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(#"ok");
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#" ");
NSLog(#"error : %#", error);
}];
}
Thanks
I'm trying to make a ad post . I Set everything up as I thought it would be right however when I click the boson "cadastrar anuncio" it returns this error "got 422". already researched about the error however could not fix at all.
someone here has gone through this?
this is my web service
#import "JVWebService.h"
#import <RestKit/RestKit.h>
#import "AppDelegate.h"
#import "JVUtils.h"
#import "Ads.h"
static NSString *kServerURL = #"http://localhost:3000";
#interface JVWebService ()
#property (strong, nonatomic) RKObjectManager *restKitObjectManager;
#property (strong, nonatomic) NSDictionary *adAttributes;
#property (strong, nonatomic) NSDictionary *postAdAttributes;
#property (strong, nonatomic) NSDictionary *userAttributes;
#property (strong, nonatomic) NSDictionary *postUserAttributes;
#end
#define kSuccessStatusCode RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)
#implementation JVWebService
+ (instancetype)sharedService {
static JVWebService *sharedService = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedService = [[self alloc] init];
[AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
sharedService.restKitObjectManager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:kServerURL]];
[sharedService.restKitObjectManager.HTTPClient setAuthorizationHeaderWithUsername:[[[AppDelegate sharedDelegate] currentUser] email]
password:[[[AppDelegate sharedDelegate] currentUser] password]];
});
return sharedService;
}
#pragma mark - User
- (void)getUserForEmail:(NSString *)email andPassword:(NSString *)password {
RKObjectMapping *objectMapping = [RKObjectMapping mappingForClass:User.class];
[objectMapping addAttributeMappingsFromDictionary:self.userAttributes];
RKObjectMapping *requestMapping = [RKObjectMapping requestMapping];
[requestMapping addAttributeMappingsFromDictionary:self.postUserAttributes];
NSString *path = #"/users/sign_in.json";
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:requestMapping
objectClass:User.class
rootKeyPath:#"user"
method:RKRequestMethodAny];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:objectMapping
method:RKRequestMethodAny
pathPattern:path
keyPath:#"user"
statusCodes:kSuccessStatusCode];
[self.restKitObjectManager addRequestDescriptor:requestDescriptor];
[self.restKitObjectManager addResponseDescriptor:responseDescriptor];
User *user = [User new];
user.email = email;
user.password = password;
[[NSUserDefaults standardUserDefaults] setObject:[[NSUUID UUID] UUIDString] forKey:#"authencity_token"];
NSDictionary *params = #{#"authenticity_token" : [[NSUserDefaults standardUserDefaults] objectForKey:#"authencity_token"]};
[self.restKitObjectManager.HTTPClient setAuthorizationHeaderWithUsername:email password:password];
[self.restKitObjectManager postObject:user path:path parameters:params success:^(RKObjectRequestOperation *operation,
RKMappingResult *result){
User *user = (User *)result.array.firstObject;
user.password = password;
[[AppDelegate sharedDelegate] login:user];
[[AppDelegate sharedDelegate] setLoggedViaFacebook:NO];
if ([self.serviceDelegate respondsToSelector:#selector(successfulRequestDidReturnObject:)])
[self.serviceDelegate successfulRequestDidReturnObject:user];
} failure:^(RKObjectRequestOperation *operation, NSError *error){
RKLogError(#"Operation failed with error: %#", error);
if ([self.serviceDelegate respondsToSelector:#selector(requestDidFailWithError:)])
[self.serviceDelegate requestDidFailWithError:error];
}];
[self.restKitObjectManager removeResponseDescriptor:responseDescriptor];
}
- (void)postAd:(Ads *)ad {
NSString *path = #"/ads.json";
RKObjectMapping *objectMapping = [RKObjectMapping mappingForClass:Ads.class];
[objectMapping addAttributeMappingsFromDictionary:self.adAttributes];
RKObjectMapping *requestMapping = [RKObjectMapping requestMapping];
[requestMapping addAttributeMappingsFromDictionary:self.postAdAttributes];
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:requestMapping
objectClass:Ads.class
rootKeyPath:#"ad"
method:RKRequestMethodAny];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:objectMapping
method:RKRequestMethodAny
pathPattern:path
keyPath:#"ad"
statusCodes:kSuccessStatusCode];
[self.restKitObjectManager addRequestDescriptor:requestDescriptor];
[self.restKitObjectManager addResponseDescriptor:responseDescriptor];
NSMutableURLRequest *urlRequest = [self.restKitObjectManager multipartFormRequestWithObject:ad method:RKRequestMethodPOST path:path parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
// NSArray *photosArray = ad.photos[0];
// for(int i = 0; i < photosArray.count; i++) {
//
// NSString *name = [NSString stringWithFormat:#"ad[photos_attributes][%i][picture]", i];
// NSString *fileName = [NSString stringWithFormat:#"photo%i.jpg", i];
// [formData appendPartWithFileData:UIImagePNGRepresentation(photosArray[i])
// name:name
// fileName:fileName
// mimeType:#"image/jpg"];
// }
}];
RKObjectRequestOperation *operation = [self.restKitObjectManager objectRequestOperationWithRequest:urlRequest
success:^(RKObjectRequestOperation *operation, RKMappingResult *result) {
if ([self.serviceDelegate respondsToSelector:#selector(successfulRequestDidReturnObject:)])
[self.serviceDelegate successfulRequestDidReturnObject:nil];
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
if ([self.serviceDelegate respondsToSelector:#selector(requestDidFailWithError:)])
[self.serviceDelegate requestDidFailWithError:error];
}];
[self.restKitObjectManager enqueueObjectRequestOperation:operation];
[self.restKitObjectManager removeRequestDescriptor:requestDescriptor];
[self.restKitObjectManager removeResponseDescriptor:responseDescriptor];
}
- (NSDictionary *)adAttributes {
return #{
#"id" : #"_id",
#"title" : #"title",
#"price" : #"price",
#"local" : #"local",
#"description" : #"especification"
// #"categories" : #"categories",
// #"photos" : #"photos",
// #"latitude" : #"latitude",
// #"longitude" : #"longitude"
};
}
- (NSDictionary *)postAdAttributes {
return #{
#"_id" : #"id",
#"title" : #"title",
#"price" : #"price",
#"local" : #"local",
#"especification" : #"description"
// #"categories" : #"category_ids",
// #"user_id" : #"user_id",
// #"latitude" : #"latitude",
// #"longitude" : #"longitude"
};
}
- (NSDictionary *)userAttributes {
return #{
#"id" : #"_id",
#"email" : #"email",
#"name" : #"name",
#"avatar" : #"profileImageUrl",
#"phone" : #"phone",
#"password" : #"password",
#"contact_pref" : #"communicationPreference",
#"products_alerts" : #"productsAlerts"
};
}
- (NSDictionary *)postUserAttributes {
return #{
#"_id" : #"id",
#"email" : #"email",
#"name" : #"name",
#"phone" : #"phone",
#"password" : #"password",
#"password" : #"password_confirmation",
#"communicationPreference" : #"contact_pref"
};
}
#end
this is my NewAdViewController:
#import "NewAdViewController.h"
#import "Ads.h"
#import "JVUtils.h"
#import "JVWebService.h"
#import "AppDelegate.h"
#interface NewAdViewController ()
#end
#implementation NewAdViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)signUp:(id)sender {
if (self.titleField.text.length <= 0) {
[JVUtils showMessage:#"Falta algo ae eem =D =D fdp." withTitle:#"Opa!"];
} else if (self.priceField.text.length <= 0) {
[JVUtils showMessage:#"Falta algo ae eem =D =D fdp" withTitle:#"Opa!"];
} else if (self.localField.text.length <= 0) {
[JVUtils showMessage:#"Falta algo ae eem =D =D fdp" withTitle:#"Opa!"];
} else if (self.descriptionField.text.length <= 0) {
[JVUtils showMessage:#"Falta algo ae eem =D =D fdp" withTitle:#"Opa!"];
} else {
Ads *newAd = [Ads new];
newAd.title = self.titleField.text;
newAd.price = self.priceField.text;
newAd.local = self.localField.text;
newAd.especification = self.descriptionField.text;
[[JVWebService sharedService] setServiceDelegate:self];
[[JVWebService sharedService] postAd:newAd];
}
}
- (void)successfulRequestDidReturnObject:(NSObject *)object {
[JVUtils showMessage:#"Anuncio cadastrado =D" withTitle:#"hadoukeeeen !"];
[[AppDelegate sharedDelegate] setCurrentUser:(User *)object];
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)requestDidFailWithError:(NSError *)error {
[JVUtils showMessage:error.localizedDescription withTitle:#"Errohue"];
}
-(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
}
#end
Here is the detail from the server log
Started POST "/ads.json" for 127.0.0.1 at 2015-03-03 18:06:15 -0300
Processing by AdsController#create as JSON Parameters:
{"ad"=>{"description"=>"ewewe", "id"=>"", "local"=>"ew",
"price"=>"25", "title"=>"titulp"}} User Load (0.6ms) SELECT users.*
FROM users WHERE users.id = 2 ORDER BY users.id ASC LIMIT 1
Unpermitted parameters: id (0.2ms) BEGIN (0.6ms) ROLLBACK Completed
422 Unprocessable Entity in 10ms (Views: 0.3ms | ActiveRecord: 1.4ms)
Status code 422 indicates that your data was incorrect in some way - the request was well formed but the data couldn't be processed.
Looking at the log from the server you can see that id is empty and there is an error message Unpermitted parameters: id
You need to determine why id is empty and correct this before you send a request.
Am i doing something weired here ?
my categories get downloaded and mapped,
product also get downloaded and mapped as logging is saying,
but my products are empty under each category,
thnx!
{
"productsCategories" : [
{
"product" : [
{
"price" : 3.99,
"title" : "Product A"
},
{
"price" : 3.99,
"title" : "ProductB "
}
],
"categoryTitle" : “a category“
}
]
}
RKObjectMapping *productCategoryMapping = [RKObjectMapping mappingForClass:[ProductCategory class]];
[productCategoryMapping addAttributeMappingsFromDictionary:#{
#"categoryTitle": #"tit"
}];
RKObjectMapping* productMapping = [RKObjectMapping mappingForClass:[Product class] ];
[productMapping addAttributeMappingsFromDictionary:#{
#"title": #"tit",
#"price": #"prc"
}];
[productCategoryMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"product"
toKeyPath:#"product"
withMapping:productMapping]];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:productCategoryMapping method:RKRequestMethodPOST pathPattern:#"productByCategory" keyPath:#"productsCategories" statusCodes:[NSIndexSet indexSetWithIndex:200]];
NSURL *url=[NSURL URLWithString:#"http://www.example.com/REST/v2/"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:url];
[manager addResponseDescriptor:responseDescriptor];
NSMutableDictionary *mutableParameters = [NSMutableDictionary dictionary];
[mutableParameters setValue:#"1" forKey:#"id"];
[manager addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:productCategoryMapping method:RKRequestMethodPOST pathPattern:#"productByCategory" keyPath:#"productsCategories" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]];
[manager postObject:request path:#"productByCategory" parameters:mutableParameters success:^(RKObjectRequestOperation *operation, RKMappingResult *result){
self.productCategoryArr=result.array;
[self.tblDetails reloadData];
}failure:^(RKObjectRequestOperation *operation, NSError *error) {
RKLogError(#"Operation failed with error: %#", error);
self.productCategoryArr=nil;
}];
the logging says objects are being mapped for each products but I only get
ProductCategory: 0x7bf53510
ProductCategory: 0x7be57f00
arrays and 0 objects in each
Assuming your ProductCategory class has
NSArray *Product
NSString * tit
Create a top level RKObjectMapping like,
RKObjectMapping * ProductCategoryResponseMapping = [RKObjectMapping mappingForClass: [ProductCategoryResponse class]];
[ProductCategoryResponseMapping addAttributeMappingsFromDictionary:#{
#"productsCategories": #"productsCategories"
}];
And create new class ProductCategoryResponse which should have
NSArray * productsCategories
Use ProductCategoryResponseMapping for Response descriptor.
Now your response will have array of productsCategories, each having array of Products and String tit.
I have used RestKit and made a mapping with a managed object. I then use the postObject method but I have a problem when retrieved the body as it maps to null.
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:baseURL];
// Serialize to JSON
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
[RKObjectManager setSharedManager:objectManager];
RKEntityMapping *searchInfoMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([Search class]) inManagedObjectStore: objectManager.managedObjectStore];
searchInfoMapping.identificationAttributes = #[ #"faresQueryType" ];
[searchInfoMapping addAttributeMappingsFromDictionary:#{
#"id" : #"ID",
#"type" : #"Type",
#"count" : #"Count",
#"route” : #"route”,
}];
RKObjectMapping *searchInfoRequestMapping =[RKObjectMapping requestMapping];
[searchInfoRequestMapping addAttributeMappingsFromDictionary:#{
#"id" : #"ID",
#"type" : #"Type",
#"count" : #"Count",
#"route” : #"route”,
}];
//Data mapping is a method that returns an RKObjectMapping for my model
RKResponseDescriptor * searchDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:searchInfoMapping pathPattern:nil keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptorsFromArray:#[searchDescriptor,]];
//Inverse mapping, to perform a POST
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:searchInfoRequestMapping objectClass:[Search class] rootKeyPath:nil];
[objectManager addRequestDescriptor:requestDescriptor];
[appDelegate.objectManager postObject:nil path:#"routes" parameters:postParameters success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(#"Success case %#",mappingResult);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"Failure in Flight Mapping %#",error);
[alert show];
}];
Edit
//JSON Result
{
"currency": {
"code": "USD",
"name": "U.S. Dollar",
"symbol": "US$",
"exchange_rate": 1
},
"routes": [
{
"id": "MS648-2022:MS985-2110",
"fares": [
{
"price": 745.32,
"description": "Economy",
"deeplink": "http://www.wego.com/flights/providers/2/deeplinks?search_id=CQtxCXQCRfmwhp72PAjopQ&trip_id=RUH:NYC:2013-12-20&fare_id=sky-tours.com:0&route=RUH-JFK",
"provider_code": "sky-tours.com",
"deeplink_params": {
"trip_id": "RUH:NYC:2013-12-20",
"route": "RUH-JFK",
"search_id": "CQtxCXQCRfmwhp72PAjopQ",
"fare_id": "sky-tours.com:0"
}
}
]
}
]
}
You need to supply the Search object instead of nil when you call postObject (currently you have postObject:nil). This tells RestKit which request mapping to use to send the request. As a result of not setting it the server will likely not have all of the required information (it's impossible to tell with the information provided).
For 2 days now, I've been trying to find out why I'm getting the error using iOS 6.1.3 with Xcode 4.6.2 and RestKit 0.20.0:
"...this class is not key value coding-compliant for the key Text."
The strange part is that I can receive (GET) the JSON object fine. The error happens when I create my sample SignalMessage object and then try to PUT it back to the server.
The JSON is as follows:
{"Text":"New Message","HasMessage":"true"}
The SignalMessage object looks like this:
#import <Foundation/Foundation.h>
#interface SignalMessage : NSObject {
}
#property (nonatomic, copy) NSString *signalText;
#property (nonatomic, retain) NSNumber *isHasMessage;
#end
And the implementation like this:
#import "SignalMessage.h"
#implementation SignalMessage
#synthesize isHasMessage, signalText;
#end
My correctly working getMessage function looks like this:
- (IBAction)getMessage:(id)sender;
{
NSLog(#"%#", #"Getting message... ");
NSURL *url = [NSURL URLWithString:#"http://ec2-54-243-148-145.compute-1.amazonaws.com/TabletPractice/api/signal?clientIdentifier=2"];
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:url];
RKObjectMapping *responseMapping = [RKObjectMapping mappingForClass:[SignalMessage class]];
[responseMapping addAttributeMappingsFromDictionary:#{#"Text":#"signalText", #"HasMessage": #"isHasMessage"}];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:responseMapping pathPattern:nil keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[manager addResponseDescriptor:responseDescriptor];
[manager getObject:nil path:#"" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *result)
{
NSArray *theresults = [result array];
for (SignalMessage *item in theresults) {
self.txtMessage.text = item.signalText;
[self hideControls];
}
} failure:^(RKObjectRequestOperation * operation, NSError * error)
{
NSLog (#"Server WS call failure: operation: %# \n\nerror: %#", operation, error);
}];
}
And here is the sendClicked message that gives me grieve:
- (IBAction)btnSendClicked:(id)sender;
{
if ([txtMessage.text length] < 1)
return;
NSURL *url = [NSURL URLWithString:#"http://ec2-54-243-148-145.compute-1.amazonaws.com/TabletPractice/api/signal?clientIdentifier=2"];
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:url];
RKObjectMapping *requestMapping = [RKObjectMapping requestMapping];
[requestMapping addAttributeMappingsFromDictionary:#{#"Text":#"signalText", #"HasMessage": #"isHasMessage"}];
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:requestMapping
objectClass:[SignalMessage class]
rootKeyPath:#""];
[manager addRequestDescriptor:requestDescriptor];
SignalMessage *newMessage = [[SignalMessage alloc] init];
newMessage.signalText = #"Test Message";
BOOL isMsg = TRUE;
NSNumber *boolAsNumber = [NSNumber numberWithBool:isMsg];
newMessage.isHasMessage = boolAsNumber;
[manager putObject:newMessage path:#"" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *result) {
NSLog(#"We object mapped the response with the following result: %#", result);
} failure:^(RKObjectRequestOperation * operation, NSError * error)
{
NSLog (#"Server WS call failure: operation: %# \n\nerror: %#", operation, error);
}];
[self hideControls];
}
At this point, I'm at a loss.
Please add a inverse mapping to your RKRequestDescriptor in your btnSendClicked method like below:
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor
requestDescriptorWithMapping:[requestMapping inverseMapping]
objectClass:[SignalMessage class]
rootKeyPath:#""];