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.
Related
So, basically I am trying to make a JSON Request against a WS in which one of its parameter is an Array using AFNetworking 3.0 My Json should look something like:
{
"filtrosAlerta": [
{
"data": "",
"type": ""
}
],
"frecuency": 0
}
The backend error doesn't say much really (Request failed: internal server error (500)) but after troubleshooting this in different ways, the Array inside the Dictionary seems to be the problem. So I am sending the following request through AFNetworking 3.0:
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
AFJSONRequestSerializer *serializer = [AFJSONRequestSerializer serializer];
manager.requestSerializer = serializer;
[manager.requestSerializer setAuthorizationHeaderFieldWithCredential:credential];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:#"application/json", #"text/json", #"text/javascript", #"text/html",nil];
NSString *url = #"http://www.example.com/webservice"
NSArray *filters = #[#{#"data" : #"java", #"type" :#"query"}, #{#"data" : #"29", #"type" :#"provincia"}];
NSDictionary *parameters = #{#"filtrosAlerta":filters, #"frecuenciaNotif":[NSNumber numberWithInt:0]]
[manager POST:url parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nullable task, id response) {
completionBlock(response, nil);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
completionBlock(nil, error);
}];
My problem is that when I add the NSArray inside the NSDictionary I get an error from the backend server. If I try to debug the "parameters" NSDictionary inside xcode I get the following thing:
{filtrosAlerta = ({data = java;type = query;}{data = 29;type = provincia;});
frecuenciaNotif = 7;}
Please note that instead of the normal "[]" Json Array I seem to be getting a "()" array which doesn't seem to be right, but this is really xcode debugger, and I believe that eventually AFNetworking will get each object inside the NSDictionary and create the proper JSON string! I've been looking around and tried different answers but could not get this working yet.
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
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.
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. When I set a break point and look at the responseObject, it is nil. I don't know why the log is pumping out data but the value is nil in the debugger.
What I am ultimately trying to do is save the response to use it later.
Also, I am using Sculptor to help with serializing.
-(NSArray*) getPhotoForWord:(NSString*)word {
NSArray *results = nil;
__block NSMutableDictionary *test = 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, id responseObject) {
NSLog(#"JSON: %#", responseObject);
test = responseObject;
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
return results;
}
You never set results variable, so of course that will return nil. Even if you used test (which you do set), that happens asynchronously, so when you immediately return, it will be nil, too, only getting the responseObject value later.
You might consider employing an asynchronous pattern, instead, supplying a completion handler parameter:
- (void)getPhotoForWord:(NSString*)word completionHandler:(void (^)(id responseObject, NSError *error))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, id responseObject) {
if (completionHandler) {
completionHandler(responseObject, nil);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if (completionHandler) {
completionHandler(nil, error);
}
}];
}
You'd then call that like so:
[obj getPhotoForWord:word completionHandler:^(id responseObject, NSError *error) {
// use responseObject here
}];
// do not use it here because the above happens asynchronously (i.e. later)
It looks like you aren't assigning results to anything. The only 2 times it appears in your code is when you declared it:
NSArray *results = nil;
and when you return it:
return results;
What it appears you are missing is parsing your test dictionary and populating an array, then returning that?
But as gabbler said in the comments, the call is asynchronous so unless you set up a semaphore, notifications, or something along those lines to make it synchronous, the return has a chance to be nil anyways.
i have a request which returns information from a php web service. I'm having trouble adding this to a array which can be used in my UICollectionView. It seems like whatever i do i cant return the data. I think it is because i'm returning the array before i've added any objects. I've tried placing the NSLog several places, but without luck. What am i doing wrong?
When i place this NSLog(#"%d", imagesArray.count); beyond the request it returns 0.
ViewDidAppear:
-(void)viewDidAppear:(BOOL)animated {
imagesArray = [[NSMutableArray alloc] init];
[self getImages];
}
getImages method:
-(void)getImages {
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager GET:#"http://URL.COM" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:responseObject options:kNilOptions error:nil];
NSString *theTitle = [[json objectForKey:#"response"] valueForKey:#"title"];
NSString *theUrl = [[json objectForKey:#"response"] valueForKey:#"imageUrl"];
[imagesArray addObject:[[NSMutableDictionary alloc] initWithObjectsAndKeys:
theTitle, #"title",
theUrl, #"url",
nil]];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
NSLog(#"%d", imagesArray.count);
}
AFNetworking is Asynchronous, you have to place the log inside the success block. Otherwise the array will always be empty.
One good solution would be to pass a block to your getImages function like that
-(void) getImages:(void (^)(BOOL result))callback {
// your code here then you call callback(YES or NO) inside your success or failure block.
}
[self getImages:^(BOOL result){
if(result)
//we got the images, we can now display them etc.
}];