afnetworking get json data out from response - ios

I am trying to extract data(just a string) from request and set it to the NSString. I tried it in many way but it is not working. If anyone can point out my mistake, it will be very helpful for me.
json data
{
"status": 1,
"key": "1e39248f4a5e05153dc376a"
}
My code
NSString *key;
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *params = # {#"app_token" :APP_TOKEN};
[manager POST:GET_USER_KEY_URL parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSDictionary* response = (NSDictionary*) responseObject;
key=[response valueForKey:#"key"];
[[NSUserDefaults standardUserDefaults]setValue:(key) forKey:USER_KEY];
NSLog(#"NEW KEY Request: %#", key);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"NEW KEY Request error: %#", error);
}];
Just want to assign response "key" data and store it on the NSString *key;
Thank you in advance.

You have declared the variable key outside of the block. You need to add __block infront of NSString *key;
To assign a variable outside a block you have to remember the __block specifier.
Related question:
Assign a variable inside a Block to a variable outside a Block

Related

Cant parse afnetworking json response to nsdictionary

I am attempting to call an external API with the following afnetworking request code:
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc]initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
destination, #"destination",
nil];
[manager POST:baseUrl parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
completion(nil, responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
completion(error, nil);
NSLog(#"error: %#", error);
}];
When I print out the responseObject I get the following which is the json that I expect to see:
However when I attempt to access the code e.g. responseObject[#"code"] I get some strange text:
(__NSCFNumber *) $0 = 0xb00000000000fa33 (long)4003
I then tried to parse this with NSStringwithformat %ld, but that returns:
(__NSCFString *) $1 = 0x000060800005a850 #"-5764607523034170829"
Not sure what's going on here, whether the responseObject has even been parsed properly as an NSDictionary
any help would be appreciated
i'm not sure what is going on here, but I recommend to use Gloss framework for JSON Serializing/Deserializing to map JSON on objects directly.
http://harlankellaway.com/Gloss/
i'm not sure what is happening but it's strange
so i suggest you can Debug it step by step
What i suppose is that the number is a float, try
NSNumber *num = [responseObject objectForKey:#"code"];
int theValue = [num intValue];
This might help.
so what you have to do is, inside you success block,
NSDictionary *result = (NSDictionary *)responseObject;
for(NSDictionary *all in result){
int code = [all objectForKey:#"code"];
}
hope this will help to your.
note : better to use model and add those objects to a mutable array.

Wanting to use the data I get back when using AFNetworking

I am using AFNetworking to get a JSON response. I am getting is as a PhotoPXArray (model I created using mantle). The log output is exactly the data I want. My problem is using the data. How do I go about saving the response data as a variable that can be used elsewhere in my program.
Also, I am using Sculptor to help with serializing.
-(NSArray*) getPhotoForWord:(NSString*)word {
NSArray *results = nil;
NSString *requestString = BASE_URL;
requestString = [requestString stringByAppendingString:#"photos/search?term="];
requestString = [requestString stringByAppendingString:word];
requestString = [requestString stringByAppendingString:CONSUMER_KEY];
NSString *encoded = [requestString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [SCLMantleResponseSerializer serializerForModelClass:PhotoPXArray.class];
[manager GET:encoded
parameters:nil
//success:^(AFHTTPRequestOperation *operation, id responseObject) {
success:^(AFHTTPRequestOperation *operation, PhotoPXArray *responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
return results;
}
#end
Read the Apple documentation regarding blocks and variables. Or you can view this question on SO that will probably also answer your question.
From the Apple docs:
__block variables live in storage that is shared between the lexical scope of the variable and all blocks and block copies declared or
created within the variable’s lexical scope. Thus, the storage will
survive the destruction of the stack frame if any copies of the blocks
declared within the frame survive beyond the end of the frame (for
example, by being enqueued somewhere for later execution). Multiple
blocks in a given lexical scope can simultaneously use a shared
variable.
Use a completion block to get your data out:
- (void)getPhotoForWord:(NSString *)word completionHandler:(void ^(PhotoPXArray *photoArray))completionHandler
{
NSString *requestString = BASE_URL;
requestString = [requestString stringByAppendingString:#"photos/search?term="];
requestString = [requestString stringByAppendingString:word];
requestString = [requestString stringByAppendingString:CONSUMER_KEY];
NSString *encoded = [requestString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [SCLMantleResponseSerializer serializerForModelClass:PhotoPXArray.class];
[manager GET:encoded
parameters:nil
success:^(AFHTTPRequestOperation *operation, PhotoPXArray *responseObject) {
NSLog(#"JSON: %#", responseObject);
if (completionHandler) {
completionHandler(responseObject);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
Then call it like this:
[object getPhotoForWord:#"word" completionHandler:^(PhotoPXArray *photoArray) {
// Do something with photo array.
}];
Note that this call is asynchronous and will complete at some unknown time in the future. Also, you should likely take an NSError argument in the completion block so you can see if you get an error from the request, but I'll leave that to you.

Value of NSMutableDictionary is not changing inside the block

I am passing the URL in this method and getting the data as output. i want to assign a new value to nsmutabledictionary but it is not assigning the value.
-(NSDictionary*) getDatafromURL: (NSString*)url{
__block NSMutableDictionary *returnData=[[NSMutableDictionary alloc] init];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
returnData=(NSMutableDictionary*)responseObject;
NSLog(#"Data 1: %#",returnData);// it is printing the data
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
NSLog(#"Data 2: %#",returnData);// it is not printing any data
return returnData;
}
in this above example the Data 1 is showing value successfully
Data 2 gives me empty dictionary.why it is not assigning the new value?
That happens because you get to the line with "Data 2" first and the block is executed only afterwards, since it is an async request. I would suggest that you change your method to something like:
- (void)getDataFromURL:(NSString *)url completionHandler:(void (^)(NSMutableDictionary *returnData, NSError *error))handler {
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
returnData=(NSMutableDictionary*)responseObject;
NSLog(#"Data 1: %#",returnData);// it is printing the data
handler(returnData, nil);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
handler(nil, error);
}];
}
There might be some compile errors in the code I provided.
The other solution would be to do a synchronous request, in which case the block would be executed before the code that is after the block.
EDIT:
If you are choosing the first solution, you have to continue using it asynchronously. So you would call it like:
[self getDataFromURL:#"abc.com" completionHandler:^ (NSMutableDictionary *returnData, NSError *error) {
// process your dictionary and the error object
}];
Please check whether your Data 2 is printing before data 1? If yes, its because, the response object gets downloaded only after a certain delay. Take away the return statements. Pass the data to the dictionary to which you return the method. For eg: like
instead of
self.myDictionary = [self getDatafromURL:someURl];
to
-(void) getDatafromURL: (NSString*)url{
__block NSMutableDictionary *returnData=[[NSMutableDictionary alloc] init];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
returnData=(NSMutableDictionary*)responseObject;
NSLog(#"Data 1: %#",returnData);// it is printing the data
self.myDictionary = returnData;
// Continue whatever you want to do
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
Or use the dispatch methods instead of the blocks.
like
Or use manager waitUntilFinish method below.

Parsing JSON with AFNetworking into NSDictionary

I am trying to parse some JSON with AFNetworking and an NSDictionary. However something seems strange with the JSON. The JSON contains routes for shuttles, but I do not see a 'route' in the JSON.
When I run this code I get an empty NSDictionary with 15 allocated spaces.
NSString *methodURL = [NSString stringWithFormat:#"%#GetRoutesForMapWithSchedule", BASE_URL];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:methodURL parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
_routes = (NSDictionary *)responseObject;
//_route = _routes[#"Stops"];
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
Can anyone explain how I can get all the info for one route? This is the JSON.
NSArray *routes = (NSArray *)responseObject;
NSDictionary *oneRoute = responseObject[0];
NSDictionary *stops = oneRoute[#"Stops"];
The problem is that the top level JSON object is actually an array, not a dictionary as you're trying to cast it to. Each element of the array on the other hand, is a dictionary.
Here is some code to get the general data structure and to get a piece of data out of one of the routes.
NSArray *routes = (NSArray *)responseObject;
NSDictionary *firstRoute = responseObject[0];
NSString *description = firstRoute[#"Description"];
Edit: To parse Stops, you would do something like this:
NSArray *stops = firstRoute[#"Stops"];
NSDictionary *firstStop = stops[0];
NSString *stopDescription = firstStop[#"Description"];

Passing JSON object received asynchronously in block to an instance variable - using AFNetworking on iOS6

This code has the JSON but no matter what I do I haven't been able to figure out how to pass this JSON to an instance variable. Each time I set it to a variable and call that variable outside of this method its nil. So what I can gather is that the variable is called before the following async call returns.
So the question is what can I do to the following code so that I can extract the JSON value. Somewhere on the internet I read that I would need to pass it a block which would server as a call back on completion but I cannot figure out how to do that for the following code
//Gets the JSON object that contains the entries from the server
-(void)getEntriesFromServer
{
NSLog(#"%s", __PRETTY_FUNCTION__);
[[appAPIClient sharedClient] getPath:#"/entries"
parameters:nil
success:^(AFHTTPRequestOperation *operation, id JSON)
{
NSLog(#" JSON array = %#",[JSON valueForKeyPath:#"entries"]);
}failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#" Json not received");
}];
}
Thanks
try to add __block to definition of an array e.g __block NSArray* entriesArray;
or make a property like
#property (nonatomic, retain) NSArray* entriesArray;
and change your code like this
[[appAPIClient sharedClient] getPath:#"/entries"
parameters:nil
success:^(AFHTTPRequestOperation *operation, id JSON)
{
//NSLog(#" Json value received is : %# ",[JSON description]);
//NSLog(#" JSON array = %#",[JSON valueForKeyPath:#"entries"]);
self.entriesArray = [NSArray arrayWithArray:[JSON valueForKeyPath:#"entries"]];
NSLog(#" JSON array from inside block = %#", _entriesArray);
}failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#" Json not received");
}];
Hope it'll help

Resources