How would I get returningResponse (into say, a NSString) from the following code:
NSURLResponse* response;
NSError* error;
NSData* result = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:&response error:&error];
I think I can get the info that I need into a string but I can't call anything on response because it's null. Therefore, I assume that I need to call something on result. The problem is, I don't know what to call.
(The URL request has been coded prior to the code sample. I know that that works.) I want to be able to detect if the request as successful.
According to the documentation for the URL loading system:
If NSURLConnection is unable to download the URL the method will return nil and any available NSError instance by-reference in the appropriate parameter.
So, see what's in your "error" parameter to find out what the problem is.
Related
I am posting some JSON data to a server using JSONKit.
Before posting the data, I am checking the internet connection.
But if the internet connection is lost after sending request, after this line:
NSData *receivedData = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&error];
my app crashes.
I don't want to use asynchronous method here.
Is there any particular way, where I can show an alert rather than having my app crash in this situation?
I got it. if there is no internet connection, then response variable will be nil. I can check that if (response == nil) and give my alert here.
I'm trying to do a fairly basic HTTP PUT using RestKit. I don't want to put the entire object, since the API call was designed to accept a single query parameter and just update that field. I've tried two approaches so far, both unsuccessful.
URL to post to: https://myserver/api/users/{userId}
Query string parameter: verificationCode=
Example usage: PUT https://myserver/api/users/101?verificationCode=646133
Approach #1: Put the query parameter in a RKParams object and make the PUT call with those params.
NSString *putUrl = [NSString stringWithFormat:#"/api/users/%i", [APIUserInfo sharedAPIUserInfo].apiUserIdx];
NSLog(#"the PUT url is %#", putUrl);
// Send a PUT to a remote resource. The dictionary will be transparently
// converted into a URL encoded representation and sent along as the request body
NSDictionary* paramsDict = [NSDictionary dictionaryWithObject:[_verificationCode text] forKey:#"verificationCode"];
// Convert the NS Dictionary into Params
RKParams *params = [RKParams paramsWithDictionary:paramsDict];
[[RKClient sharedClient] put:putUrl params:params delegate:self];
Approach #2: Build the entire url and try a PUT with params set to nil.
NSString *putUrl = [NSString stringWithFormat:#"/api/users/%i?verificationCode=%#", [APIUserInfo sharedAPIUserInfo].apiUserIdx, [_verificationCode text]];
NSLog(#"the PUT url is %#", putUrl);
[[RKClient sharedClient] put:putUrl params:nil delegate:self];
Neither approach is working for me. The first fails saying "RestKit was asked to retransmit a new body stream for a request. Possible connection error or authentication challenge?" then runs for about 10 seconds and times out. The second approach fails saying HTTP Status 405 - Method Not Allowed.
Can anyone point out where I'm going wrong, or provide me with a simple PUT example using RestKit? Most of the examples I've found at there are putting the entire object which I don't want to do in this case.
UPDATE:
Approach #2 worked well once I got a few things sorted out on the server side. Final solution:
NSString *putUrl = [NSString stringWithFormat:#"/api/users/verify/%i?verificationCode=%#", [APIUserInfo sharedAPIUserInfo].apiUserIdx, [_verificationCode text]];
NSLog(#"the PUT url is %#", putUrl);
[[RKClient sharedClient] put:putUrl params:nil delegate:self];
the HTTP PUT method is disabled on your webserver. It is by default on all webserver for security reasons.
HTTP Status 405 - Method Not Allowed.
Is there a way with NSJSONSerialization to check that the NSData is valid JSON? I don't want the application to error out if the API returns invalid JSON for some reason.
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
NSError *error;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
This won't "error out", it'll just return nil if the JSON isn't valid. Thus the test to see if it is valid JSON would be:
NSError *error;
if ([NSJSONSerialization JSONObjectWithData:data
options:kNilOptions
error:&error] == nil)
{
// Handle error
}
If it does return nil then you can check error to see what went wrong.
NSJSONSerialization Class have a method to do exactly this... (EDIT: no it doesn't...)
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
id jsonObj = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
BOOL isValid = [NSJSONSerialization isValidJSONObject:jsonObj];
EDIT: (After hypercrypts' comment)
Hypercrypt is right (I really can't understand how I missed that)...
Even though my answer seems to be working, it's wrong.
What isValidJSONObject: method does is to check if an object can be serialized into JSON and not the other way round. So his answer is what you're looking for. You could use though this method in the case you grab a mutable copy from a json payload, mutate it and later want to check if it's safe to try and re-serialize it back to a JSON string. But bottom line is that hypercrypt's answer is the correct one and I think that it would be more than fair to mark his answer as correct instead of mine. Anyway, sorry about any confusion and #hypercrypt thank's for pointing that out :)
There isn't really a way to check the data without creating the object with NSJSONSerialization; I would put it in a try-catch. If you end up in the catch block, it's not valid JSON.
EDIT: Come to think of it, if it encountered an error, 'error' is an error object. So even if nothing is thrown you can check that to see if the data was valid.
when i try to parse the JSON response, i got an empty response and this error:
JSONValue failed. Error trace is: (
"Error Domain=org.brautaset.JSON.ErrorDomain Code=11 \"Unexpected end of string\" UserInfo=0x797c420 {NSLocalizedDescription=Unexpected end of string}"
)
This is how i try to send the JSON request and how i tried to parse its response:
send the JSON request:
- (void)viewWillAppear:(BOOL)animated{
//Specify the adress of the webservice (url)
NSURL *url = [NSURL URLWithString:#"http://xxxxxxxxxxx.com/webservices/"];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
NSString *jsonStringArray=[aMutableArray JSONRepresentation];
NSLog(#"-------------");
NSLog(#"%#",jsonStringArray);
NSLog(#"-------------");
[request setPostValue:jsonStringArray forKey:#"liste_des_themes"];
NSLog(#"The response string is: %#",request.responseString);
[request setDelegate:self];
[request startAsynchronous];
}
For the NSLog where i tried to display the json string before sending it i got a correct JSON format:
NSLog(#"%#",jsonStringArray);//["Mairie","Préfectures et sous-préfectures"]
Now for the second NSLog, i got null:
NSLog(#"The response string is: %#",request.responseString);//The response string is: (null)
When parsing the response:
-(void)requestFinished:(ASIHTTPRequest *)request
{
if(request.responseStatusCode==200)
{
NSLog(#"This block gets called, response code is 200");//This block gets called, response code is 200
//parse the response
NSLog(#"The response string is: %#",request.responseString);
NSString *responseString=[request responseString];
NSDictionary *responseDict=[responseString JSONValue];
}
}
For the NSLog trying to display the response string, i got nothing, neither null, nor a correct value:
NSLog(#"The response string is: %#",request.responseString);
//The response string is:
And after that, i got this trace error:
JSONValue failed. Error trace is: (
"Error Domain=org.brautaset.JSON.ErrorDomain Code=11 \"Unexpected end of string\" UserInfo=0x797c420 {NSLocalizedDescription=Unexpected end of string}"
)
Can you help me there? thanx in advance.
I would assume you have no control over the web service, so telling you to do something about that is generally a non-starter.
1) First, make sure that the JSON response looks correct. Can you download it into a browser and see that it looks okay?
2) If it looks okay, can it pass a JSON lint test? (Try jsonlint.com, and plug it in there.)
3) If it passes (1) and (2), then see if it has any leading nulls in the returned data response. I found this to be the case in my own code. I could not work directly with this without first removing the leading nulls.
Unfortunately, I'm not at my mac to copy the code I use to solved this problem. But it was a real problem, and the solution is to remove the nulls (There were thousands of them in my case.) Nulls in a sting look like the string terminator, so leading nulls hide the real content.
You have a problem with the web service that serves up the JSON. Debug that and you will find the problem.
I implemented a WebPolicyDelegate and the ...decidePolicyForNavigationAction:... method.
It works fine, I get among other things the HTTP method [GET|POST] but what I can't find is the actual GET and POST data. Where or how should I get it?
How about:
NSString *queryString = [[request URL] query];
NSData *postData = [request HTTPBody];
GET data is just the query string of the URI.