This is my code for requesting a JSON:
[AFJSONRequestOperation addAcceptableContentTypes:[NSSet setWithObject:#"text/html"]];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
success: ^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON){
NSArray *jsonArray =[JSON valueForKey:#"posts"];
[self postsToAnnotations:[self jsonToPosts:jsonArray] andUserLocationLat:lat Lon:lon];
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON){
NSLog(#"response %#",JSON);
NSLog(#"Failed %#",error);
[_activityView removeFromSuperview];
}];
[operation start];
}
It's working fine on simulator for iPhone 5 and in my device (iphone 4) I am getting this error:
Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (JSON text did not start with array or object and option to allow fragments not set.) UserInfo=0x208b9a80 {NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}
The problem was with the reply of the server which I was not able to see because I was using AFJSONRequestOperation. After sending the same request AFHTTPRequestOperation I was able to see the reply of the server using "result" string.
Related
I am querying my server using AFNetworking, the latest - to date - version.
My server side PHP is sending a PHP related error but I am unable to see what the error is ( so I can debug it) as AFNetworking is expecting a JSON.
Could anyone tell me how could I see the full HTTP result. I've researched and I know is something to do with operation.responseString inside the success / fail block my current block does not have AFHTTPRequestOperation* operation and I can't add it as another block variable somehow.
I would really appreciate some help.
The following code uses
NSURL *url = [[NSURL alloc]initWithString:URL];
AFHTTPClient *httpClient = [[AFHTTPClient alloc]initWithBaseURL:url];
NSURLRequest *request = [httpClient multipartFormRequestWithMethod:#"POST" path:URLPATH parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData)
{
//...
}
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON){
NSLog(#"Inside the success block %#",JSON);
[[self delegate ]shareExerciseDone:JSON];
[[self delegate] activityIndicatorFinish];
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON){
NSLog(#"Response text is: %#", operation.responseString);
NSLog(#"json text is: %#", JSON);
NSLog(#"Request failed with error: %#, %#", error, error.userInfo);
[[self delegate] activityIndicatorFinish];
}];
[operation start];
The error
Request failed with error: Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (JSON text did not start with array or object and option to allow fragments not set.) UserInfo=0xc1b4520 {NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}, {
NSDebugDescription = "JSON text did not start with array or object and option to allow fragments not set.";
Don't use AFJSONRequestOperation, just use AFHTTPRequestOperation.
For Uploading Images From iOS to Server i am using Afnetworking
can you try with this Code.and you will get response in success or failure.
NSData *userImgToUpload = UIImagePNGRepresentation(userImg.image);
NSURL *url = [NSURL URLWithString:#"www.domainname.com"];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
NSLog(#"%#",#"Uploading data");
NSDictionary *parameters = [NSDictionary dictionaryWithObjectsAndKeys:usernameTxt.text,#"username", firstnameTxt.text,#"first_name",lastnameTxt.text,#"last_name", nil];
// Upload Image
NSMutableURLRequest *request = [httpClient multipartFormRequestWithMethod:#"POST" path:#"/addPatient" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:userImgToUpload name:#"patientimage" fileName:[NSString stringWithFormat:#"%#.png",usernameTxt.text] mimeType:#"image/png"];
}];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"response: %#",[operation.responseString objectFromJSONString]);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Upload Failed");
NSLog(#"error: %#", [operation error]);
}];
[operation start];
You should listen for the AFNetworkingOperationDidStartNotification and AFNetworkingOperationDidFinishNotification events that fire at the beginning and end of the operation:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(YourOperationStartMethod:)
name:AFNetworkingOperationDidStartNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(YourOperationFinishMethod:)
name:AFNetworkingOperationDidFinishNotification
object:nil];
You can grab the operation object from the notification like this:
AFHTTPRequestOperation *operation =
(AFHTTPRequestOperation *) [notification object];
This operation object contains request and response properties.
A good example of how all this works can be found in the AFHTTPRequestOperationLogger plugin (which, of course, you could simply use, instead of writing your own thing).
I'm having difficulties to get responseString when server failed to send a valid JSON response (fe. php echos some temp variable or something went wrong). I am using AFJSONRequestOperation from AFNetwoking like this:
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id responseObject) {
NSLog(#"object: %#", responseObject);
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id responseString) {
NSLog(#"failure: %#", responseString);
}
];
responseString is case of failure is always nil. When I tried to read the documentation (http://cocoadocs.org/docsets/AFNetworking/1.3.1/Classes/AFJSONRequestOperation.html#//api/name/JSONRequestOperationWithRequest:success:failure:) I've found that there is written that failure gets three arguments (but in reality four, the fourth being always nil). Is there any simple way to get the response as a string in that case?
If responseString is nil, then you either didn't receive any data from the server, or the data could not be used to create a valid NSString object.
By the sound of your Cocoa error 3840, which corresponds to an NSJSONSerialization error, my guess is that the server was indeed sending back an empty response.
I want to connect my iOS App with AFNetwork to my webserver with a self-signed certificate. I found a solution on github (https://github.com/AFNetworking/AFNetworking/pull/694) I tried it out and the certificate pinning seems to work but i got an other error:
Error Domain=NSURLErrorDomain Code=-1012 "The operation couldn’t be completed.
(NSURLErrorDomain error -1012.)" UserInfo=0x7bc2090 {NSErrorFailingURLKey=(my domain)}
Does anybody know whether this error has to do with the AFNetworking Framework and the self signed certificate or not?
Solved:
I found the solution for the error. I had to set the SSLPinningMode to AFSSLPinningModeCertificate now it works.
AFJSONRequestOperation *operation =[AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSDictionary *resDictionary = (NSDictionary *)JSON;
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"%#",error);
}];
operation.SSLPinningMode = AFSSLPinningModeCertificate;
[operation start];
Try this work around.
AFJSONRequestOperation *operation =[AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSDictionary *resDictionary = (NSDictionary *)JSON;
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"%#",error);
}];
operation.securityPolicy.allowInvalidCertificates = YES;
[operation start];
I'm sending the following message to an instance of AFHTTPClient. I expect the success block to be sent a Foundation object (a dictionary) but the debugger shows me that JSON is a _NSCFData object. This question on SO states that I need to set the Accept header to 'application/json'. Well, I'm doing that but AFNetworking still is not decoding the JSON in the response body. If I decode the json myself using NSJSONSerialization I get an NSDictionary as I expect. What am I doing wrong?
[client setDefaultHeader:#"Accept" value:#"application/json"];
[client postPath:#"/app/open_connection/"
parameters:params
success:^(AFHTTPRequestOperation *operation, id JSON) {
NSLog(#"successful login! %#", [JSON valueForKeyPath:#"status"]);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"error opening connection");
NSAlert *alert = [NSAlert alertWithError:error];
[alert runModal];
}
];
Note: I'm programming the server in Python using Django. The content type of the response is 'application/json'
When you're working with AFHTTPClient and a JSON API, you will typically need to set all three of these settings:
httpClient.parameterEncoding = AFJSONParameterEncoding;
[httpClient setDefaultHeader:#"Accept" value:#"application/json"];
[httpClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
Now when you make requests using your client, it will know to parse the response as JSON.
[httpClient postPath:#"/app/open_connection/"
parameters:params
success:^(AFHTTPRequestOperation *operation, id response) {
NSLog(#"JSON! %#", response);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];
Here's a trick that I discovered as well. In the NSError object you can parse it and retrieve the error message (if the HTTP response had a JSON error message):
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSDictionary *JSON =
[NSJSONSerialization JSONObjectWithData: [error.localizedRecoverySuggestion dataUsingEncoding:NSUTF8StringEncoding]
options: NSJSONReadingMutableContainers
error:nil];
failureCallback(JSON[#"message"]);
}
Try this ... I think there maybe something wrong with your client settings.
NSMutableURLRequest *request = [client requestWithMethod:#"POST" path:#"/app/open_connection/" parameters:params];
AFJSONRequestOperation *operation =
[AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(#"successful login! %#", [JSON valueForKeyPath:#"status"]);
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"error opening connection");
NSAlert *alert = [NSAlert alertWithError:error];
[alert runModal];
}];
[operation start];
I have the following code for JSON Parsing:
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"https://www.dropbox.com/s/qz16qyi3julygl9/facebook.json"]];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(#"Request Success %#",[JSON class]);
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"Request Failure Because %#",[error userInfo]);
}];
[operation start];
but I have Request Failure with the following error message:
NSErrorFailingURLKey = "https://www.dropbox.com/s/qz16qyi3julygl9/facebook.json";
NSLocalizedDescription = "Expected content type {(\n \"text/json\",\n \"application/json\",\n \"text/javascript\"\n)}, got text/html";
can somebody help me?
In my errorlog it prints "got text/html". So just add
[AFJSONRequestOperation addAcceptableContentTypes:[NSSet setWithObject:#"text/html"]]
It works.
[AFJSONRequestOperation addAcceptableContentTypes:#"text/plain"]
The above is deprecated from AFNetworking 2.x. Instead you can call the following on the instance of the AFHTTPRequestOperation as follows
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/plain"];
Where manager is your instance of AFHTTPRequestOperation.
Source: https://github.com/AFNetworking/AFNetworking/issues/1381
Because the link you provide doesn't hotlink the file. It links to an HTML page to download the file. Try going there in a browser...
Try this link instead: https://dl.dropbox.com/s/qz16qyi3julygl9/facebook.json?dl=1 No guarantees it will work though. A lot of companies frown on directly linking to files in this way.