Can someone explain mapping Restkit Get results mapping into an Array - restkit

I've been through the available documentation including https://github.com/RestKit/RestKit/wiki/Object-mapping and I haven't been able to find an explanation or examples to map GET results in
(void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects
What exactly is (NSArray*)objects ?
When I returned just one JSON object from the server I was able to map it with :
NSString *bodyResults;
bodyResults = [[objectLoader response] bodyAsString];
NSDictionary *resultsDictionary = [bodyResults objectFromJSONString];
NSString *subject = [resultsDictionary objectForKey:#"subject"];
But now that i'm returning a JSON list (a selection of objects) I'm having trouble.
I'm mapped the object before submitting the get:
//map offering
RKObjectMapping* offeringMapping = [RKObjectMapping mappingForClass:[Offering class]];
[offeringMapping mapKeyPath:#"categoryId" toAttribute:#"categoryId"];
[offeringMapping mapKeyPath:#"merchantId" toAttribute:#"merchantId"];
[offeringMapping mapKeyPath:#"name" toAttribute:#"name"];
[offeringMapping mapKeyPath:#"latitude" toAttribute:#"latitude"];
[offeringMapping mapKeyPath:#"longitude" toAttribute:#"longitude"];
[[RKObjectManager sharedManager].mappingProvider setMapping:offeringMapping forKeyPath:#"offering"];
double latitude = [(AppDelegate*)[[UIApplication sharedApplication] delegate] currentLatitude];
double longitude = [(AppDelegate*)[[UIApplication sharedApplication] delegate] currentLongitude];
NSString *latitudeString = [[NSNumber numberWithDouble:latitude] stringValue];
NSString *longitudeString = [[NSNumber numberWithDouble:longitude] stringValue];
NSDictionary *getParams = [NSDictionary dictionaryWithKeysAndObjects:
#"lat",latitudeString,
#"long",longitudeString,
nil];
[[RKObjectManager sharedManager] loadObjectsAtResourcePath:[#"/merchantofferings" stringByAppendingQueryParameters:getParams] delegate:self];
Thanks

In response to your first question, (NSArray *)objects is an array of the objects that were loaded by the objectLoader. So in your case, they should be objects of type Offering populated with the attributes that you mapped in the object mapping.
Do you have a sample of the JSON that you're returning from the GET request that you can post here? Are you sure that it's valid JSON and is being returned exactly as you anticipate?

Related

NSMutableDictionary entry corrupted after departing from the method where entry was added

I use setObject:forKey: to add an object of type Rresource to a NSMutableDictionary named: resourceLib.
Then I immediately look at what's actually in the dictionary and it's OK.
When I try to look at it again in another object's method, the proper key is present but a reference to a string property "url" cases a list of error messages including:
2016-09-28 11:32:42.636 testa[760:16697] -[__NSCFString url]: unrecognized selector sent to instance 0x600000456350
Rresource object is defined as:
#interface Rresource : NSObject
#property (nonatomic,strong) NSString* url;
#property (nonatomic,strong)NSMutableArray* resourceNotesArray;
#property(nonatomic,strong)NSString* name;
#property(nonatomic,strong)NSString* resourceUniqueID;
#property(nonatomic)BOOL isResourceDirty;
This method in a ViewController adds the Rresource to the NSMutableDictionary
-(void)saveResource
{
Rresource* resource = self.currentResource;
Rresource* temp;
if (resource)
{
if ( resource.isResourceDirty)
{
[self.model.resourceLib setObject:resource forKey:resource.resourceUniqueID];
temp = [self.model.resourceLib objectForKey:resource.resourceUniqueID];
}
}
}
Resource and temp contain identical info showing the info was added correctly.
In model's method the following causes the error message described above.
for (Rresource* resource in self.resourceLib)
{
NSString* string = resource.url;
}
where model contains:
#property(nonatomic,strong)NSMutableDictionary* resourceLib;
and :
#implementation Model
- (instancetype)init
{
self = [super init];
if (self)
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
self.path = [[paths objectAtIndex:0] stringByAppendingString:#"/Application Support/E2"];
BOOL exists = [[NSFileManager defaultManager] createDirectoryAtPath:self.path withIntermediateDirectories:NO attributes:nil error:nil];
if (!exists)
{
[[NSFileManager defaultManager] createDirectoryAtPath:self.path withIntermediateDirectories:NO attributes:nil error:nil];
}
self.resourceLibPath = [NSString pathWithComponents:#[self.path,#"resources"]];
self.resourceLib = [[NSMutableDictionary alloc]init];
self.noteLibPath = [NSString pathWithComponents:#[self.path, #"notes"]];
self.noteLib = [[NSMutableDictionary alloc]init];
}
return self;
I have found this question difficult to ask clearly even after spending several hours formulating it. I apologize.
I've tried pretty much everything for about a week. I'm stumped.
Any ideas?
Thanks
According to this entry on Enumeration, when you iterate over a dictionary using the fast enumeration syntax, you're iterating over its keys. In the above code sample you're assuming the enumeration happens over its values. What you're effectively doing is casting an NSString object as an Rresource, and sending it a selector only an actual Rresource object can respond to.
This should fix the loop:
for (NSString* key in self.resourceLib)
{
NSString* string = [self.resourceLib objectForKey:key].url;
}

Write Core Data to XML file

I am trying to write the data of core data to a xml file.
What is the best way? Using an arraycontroller which propably could provide the data?
Or try with NSFetchRequest? I tried the last but I think the output of the NSFecthRequest can not written to a xml file.
I used this code:
NSManagedObjectContext *moc = [self managedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"LanguageEntity" inManagedObjectContext:moc];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDescription];
[request setReturnsObjectsAsFaults:NO];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"1==1"];
[request setPredicate:predicate];
NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:#"language" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:descriptor];
NSError *error;
NSArray *array = [moc executeFetchRequest:request error:&error];
NSLog(#"%#", array);
if (array == nil)
{
NSLog(#"error");
}
else
{
NSString *root = #"/Users/Sebastian/Desktop/A6/A6/newPlist.xml";
if (![[NSFileManager defaultManager]fileExistsAtPath:root])//checking fileexist or not
{
//if not exist creating the same
[[NSFileManager defaultManager]createFileAtPath:root contents:nil attributes:nil];
[[moc executeFetchRequest:request error:&error] writeToFile:root atomically:YES];
}
else
{
[[moc executeFetchRequest:request error:&error] writeToFile:root atomically:YES];
}
}
Is this mainly the correct way? Or should I use an ArrayController? And if so can you tell me please how to do?
Later I want to be able to save the core data content to an xml file and load an other xml or something particular.
Kind regards
How you get the data is really beside the point. Your issue is with converting the data into a form which can be exported to XML and how you process that data.
By using:
[[moc executeFetchRequest:request error:&error] writeToFile:root atomically:YES];
(firstly you are re-executing a fetch that you have already executed) you are trying to directly convert an array of managed objects into XML (in a plist format). This isn't necessarily going to work because a plist has a very specific set of allowed data types, and managed objects aren't one of them.
You could change the fetch to return dictionaries (NSDictionaryResultType), and this would get you closer. But, any dates in the data you fetch would still cause it to fail. If you have any data types that can't be stored into a plist then you will need to perform a conversion into another data type before you try to convert the array.

post an object to ASP.NET Web API using AFNetworking

the question is simple but I saw the implementation is fairly awkward!!
I want to post an object e.g. Device object to web api web service
// Initialize Client
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:#"http://rezawebapi.com"]];
//Indicationg this device is online and sending its dEVICE token to the server
Device *device = [Device new];
device.DeviceToken = [[NSUserDefaults standardUserDefaults] objectForKey:#"devicetoken"];
device.IsOnline = #"True";
//updating current active users of this app in the server
NSDictionary *dictionary = [[NSDictionary alloc]initWithObjectsAndKeys:
device.DeviceToken,#"DeviceToken",
device.IsOnline,#"IsOnline",
nil];
client.parameterEncoding = AFJSONParameterEncoding;
[client postPath:#"/api/iosAppstats" parameters:dictionary success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"%#", responseObject);
// it crashes on the next line because responseObject is NSData
}failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"%#", error.localizedDescription);
}];
1- is there anyway to send the object without creating an dictionary ?(it is error prone!)
2- when my deviceToken is null the object which it sends to the server is null. but consider here one property deviceToken is null but other properties have their own values! does anyone have any idea?
3- I have defined #property (assign, nonatomic) BOOL IsOnline; but when It creates the dictionary EXEX-BAD-ACCESS rises! how should I define bool value? (I had to define it as NSString. it is not an approved way)
1.
is there anyway to send the object without creating an dictionary ?(it is error prone!)
Your API takes JSON. JSON is just dictionaries, arrays, strings, and numbers. So, no. However, it is not error-prone. Just make sure to only put JSON-compliant objects in your dictionary. Read the NSJSONSerialization Overview for more info.
2.
when my deviceToken is null the object which it sends to the server is null. but consider here one property deviceToken is null but other properties have their own values! does anyone have any idea?
You could add deviceToken conditionally, like so:
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
NSString *deviceToken = [[NSUserDefaults standardUserDefaults] objectForKey:#"devicetoken"];
if (deviceToken) {
[dictionary setObject:deviceToken forKey:#"DeviceToken"];
}
3.
I have defined #property (assign, nonatomic) BOOL IsOnline; but when It creates the dictionary EXEX-BAD-ACCESS rises! how should I define bool value? (I had to define it as NSString. it is not an approved way)
Using a BOOL violates this rule from the NSJSONSerialization overview I linked to in #1:
All objects are instances of NSString, NSNumber, NSArray, NSDictionary, or NSNull.
So if your property is a BOOL or other simple numerical type, wrap it in #() to make it an NSNumber:
[dictionary setObject:#(device.IsOnline) forKey:#"DeviceToken"];
This is the same as:
NSNumber *isOnlineNum = [NSNumber numberWithBool:device.isOnline];
[dictionary setObject:isOnlineNum forKey:#"DeviceToken"];

Core Data Returns incorrect value (although nearly right)

Okay so I ask the Core Data for a record (userKey), in that record is a PublicKey which I am extracting, however, publicKey ends up being 90% right but has a few extra characters at the beginning and is encapsulated in brackets.
I think my problem is I am getting a pointer rather than the data from the userMatches. Any guidance would be appreciated.
AppDelegate *appdelagate = [[UIApplication sharedApplication]delegate];
context = [appdelagate managedObjectContext];
NSEntityDescription *entitydesc = [NSEntityDescription entityForName:#"KeyData" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc]init];
predicate = [NSPredicate predicateWithFormat:#"userKeyCD = %#", userKey];
[request setEntity:entitydesc];
[request setPredicate:predicate];
userMatches = [context executeFetchRequest:request error:&error];
NSString *publicKey = [userMatches valueForKey:#"publicKeyCD"];
Okay so I changed the last line to this and it worked fine;
NSString *publicKey = [[userMatches objectAtIndex:0] valueForKey:#"publicKeyCD"];
I did not show how it was defined but userMatches is an NSArray (sorry). It is used in a similar way further up the code;
NSArray *userMatches = [context executeFetchRequest:request error:&error];
Now I think about it is an array the right type?

Sorting NSJSON arrays aren't working properly

In my json file I have a title, subtitle, and url.
I sort the title to set the items alphabetically, but the url isn't sorted with the title and I don't know why.
This is what i've done:
NSDictionary *allDataDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:nil];
NSArray *arrayOfItems = [allDataDictionary objectForKey:#"items"];
for (NSDictionary *diction in arrayOfItems) {
NSString *titles = [diction objectForKey:#"title"];
NSString *station = [diction objectForKey:#"url"];
[jsonArray addObject:titles];
[jsonStations addObject:station];
// SORT JSON
NSArray *sortedArray;
sortedArray = [jsonArray sortedArrayUsingComparator:^NSComparisonResult(NSString *title1, NSString *title2)
{
if ([title1 compare:title2] > 0)
return NSOrderedDescending;
else
return NSOrderedAscending;
}];
[jsonArray setArray:sortedArray];
When I press the first item in the tableView, I get get the url from a total diffrent title.
What should I do to get the title to match the url in the tableView?
First of all this seems like a strange way of sorting, you should use a dictionary instead of 2 arrays otherwise things get messy very quickly.
Secondly you need to pass your sortedArray to the table instead of the jsonArray currently it seems to be just trying to reset the jsonArray.
I would create one method to handle it like this (I have stripped some of your sorting script to simplify this)
-(NSArray *)sortContentWithJSONData {
NSDictionary *allDataDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:nil];
NSArray *arrayOfItems = [allDataDictionary objectForKey:#"items"];
NSArray *sortedArray = [NSSortDescriptor sortDescriptorWithKey:#"title" ascending:false];
NSMutableArray *outputArray = [[NSMutableArray alloc] init];;
for (NSDictionary *diction in arrayOfItems) {
NSString *titles = [diction objectForKey:#"title"];
NSString *station = [diction objectForKey:#"url"];
[outputArray addObject:[NSDictionary dictionaryWithObjectsAndKeys:titles, #"title", station, #"station", nil]]
}
return [outputArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortedArray]];
}
Then you could set a global array and access it in your table view using the following...
NSArray *tableContent = [self sortContentWithJSONData];
Hope that clears things up a bit :)

Resources