I have the following code in the IOS SDK I am building:
+ (void) makeRequestToEndPoint:(NSString *) endpoint values:(NSMutableDictionary *) params onCompletion:(SDKCompletionBlock) responseHandler
{
[params setObject: key forKey: #"key"];
NSString * urlString = [self createApiUrlFromEndpoint: endpoint];
NSURL * url = [NSURL URLWithString: urlString];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL: url];
request.HTTPMethod = #"POST";
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"charset" forHTTPHeaderField:#"utf-8"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
request.HTTPBody = [[params urlEncodedString] dataUsingEncoding:NSUTF8StringEncoding];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
NSError * dicError = nil;
NSDictionary * dictionary = nil;
if([data length] >= 1) {
dictionary = [NSJSONSerialization JSONObjectWithData: data options:kNilOptions error: &dicError];
}
responseHandler(dictionary, error);
}];
}
So that people using the SDK can make API calls by doing the following:
[SDK makeRequestToEndpoint: #]
What is the best way to structure (best way to handle error handling, response handling, etc) the code above to make easy for people to use the SDK?
There are many open source frameworks from which you can learn good design practices for asynchronous networking. I recommend you take a look at
AFNetworking
Related
I want to add my token in Authorization header
NSURL *url2 = #"http://54.149.31.77:3000/api/search?number=98745612661";
NSLog(#"%# urlis ====>",urlString);
NSData *data = [NSData dataWithContentsOfURL:url2];
NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSData *dataaa = [ret dataUsingEncoding:NSUTF8StringEncoding];
id json = [NSJSONSerialization JSONObjectWithData:dataaa options:0 error:nil];
NSArray * resultDict =[json objectForKey:#"name"];
You can use NSMutableRequest -
NSURL *url2 = #"http://54.149.31.77:3000/api/search?number=98745612661";
NSURLSession *session = [NSURLSession sharedSession];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url2];
[request setHTTPMethod:#"GET"];
[request setValue:[[NSUserDefaults standardUserDefaults] valueForKey:#"token"] forHTTPHeaderField:#"Authorization"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
// add any additional headers or parameters
NSURLSessionDataTask *downloadTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (!error) {
// do your response handling
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSArray * resultDict =[json objectForKey:#"name"];
}
}];
[downloadTask resume];
To understand in more detail about NSURLSession refer to this Tutorial
NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:url];
[request addValue:VALUE forHTTPHeaderField:#"Authorization"];
Try to create a Mutable request and add your authorization header to it. You can send this request as a parameter to any one. Either to AFNetworking (or some third party network) library API calls or to URLSession (by Apple)
For more info on NSMutableRequest
You can pass it by
[request setValue:#"Your Token" forHTTPHeaderField:#"Authorization"];
Edited :
As per your comment if you want to change your response then your should use NSMutableDictionary instead of NSArray like.
Note: Your response should Dictionary if it will array then use NSMutableArray
NSMutableDictionary * resultDict =[json objectForKey:#"name"];
[resultDict setObject:#"Your Token" forKey:#"Authorization"];
I am fetching data using POST method. And I have successfully retrieved all the data.It's taking too long to display it in UI but I can print it immediately on console, my code is
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:#"http://www.xxxyyy.com/v1/api/client/authorize"]];
[request setHTTPMethod:#"POST"];
[request setValue:#"ABCD" forHTTPHeaderField:#"Authkey"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
[[session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
{
NSString *requestReply = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
[request setValue:#"application/json;charset=UTF-8" forHTTPHeaderField:#"Authkey"];
NSData* data1 = [requestReply dataUsingEncoding:NSUTF8StringEncoding];
jsonReturnArray = [NSJSONSerialization JSONObjectWithData:data1 options:NSJSONReadingAllowFragments error:&error];
NSArray *array = [jsonReturnArray copy];
[self rec:array];
NSString *phoneNumber=[NSString stringWithFormat:#"%#",[jsonReturnArray valueForKey:#"phone"]];
lblPhoneNumber.text = phoneNumber;
NSString *Address=[NSString stringWithFormat:#"%# %# %#,CA %#",[jsonReturnArray valueForKey:#"street1"],[jsonReturnArray valueForKey:#"street2"],[jsonReturnArray valueForKey:#"city"],[jsonReturnArray valueForKey:#"postalcode"]];
lblAddress.text=Address;//takes long time to display
NSLog(#"%#",Address);//immeaditely print
strlatitude=[jsonReturnArray valueForKey:#"latitude"];
strlongitude=[jsonReturnArray valueForKey:#"longitude"];
[self Map:(MKMapView *)mapLocation didUpdateUserLocation:(MKUserLocation *)nil];//method call
}] resume];
This is take too time to print data, but if you use NSURLConnection class it may be help you.This is my Class method it may be helpful.
+ (void)postRequestData:(NSDictionary *)postVars
Action:(APIMode)action
WithCompletionHandlar:(void (^) (id result, BOOL status))completionBlock
{
NSURL *url = [NSURL URLWithString:API_URL([self getAPINameForType:action])];
NSLog(#"Request URL %#",[NSString stringWithFormat:#"%#",url]);
NSString *contentType = #"application/json";
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request addValue:contentType forHTTPHeaderField: #"Content-Type"];
NSError *err = nil;
NSMutableDictionary *params=[[NSMutableDictionary alloc] initWithDictionary:postVars];
// [params setObject:[self getAPINameForType:action] forKey:#"mode"];
NSLog(#"Paramater %#",params);
NSData *body = [NSJSONSerialization dataWithJSONObject:params options:NSJSONWritingPrettyPrinted error:&err];
[request setHTTPBody:body];
[request addValue:[NSString stringWithFormat:#"%lu", (unsigned long)body.length] forHTTPHeaderField: #"Content-Length"];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError)
{
if(!connectionError)
{
NSError *error = nil;
NSDictionary *dictResponse = [NSDictionary dictionaryWithDictionary:[NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingAllowFragments error:&error]];
dispatch_async(dispatch_get_main_queue(), ^{
completionBlock(dictResponse,(error == nil));
});
NSLog(#"%#",dictResponse);
}
else
{
dispatch_async(dispatch_get_main_queue(), ^{
completionBlock(connectionError.localizedDescription,NO);
});
}
}];
}
Use this method instead of it.It is executed fast because NSURLConnection Class execute in background.
Try to fetch your data using NSURLConnection class(manual code) or simply use AFNetworking class(less code). AFNetworking internally uses NSURLConnection class itself.
This is my json Dictionary
{"pid":"14982","type":"intervention","uid":"10008","bookmark_g7l03":{"und":[{"value":"S:1","format":"null","safe_value":"S:1"}]}}
I need to pass the PUT request to the following URL
http://example.com/services/profiles/pid
Let us know how to pass the dictionary to Webservice URL in IOS
NSString *data = [NSString stringWithFormat:#"{\"pid\":\"%#\",\"type\":\"%#\",\"uid\":\"%#\",\"%#\":{\"und\":\[{\"value\":\"%#\",\"format\":\"null\",\"safe_value\":\"\%#\"}]}}",pid,type, uidNo,bkMarkStr,self.startString,self.startString];
NSURL *bkMrkUrl = [NSURL URLWithString:#"http://example.com/services/profiles/pid=14997"];
NSData *postData = [data dataUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest *bkMrkReq = [[NSMutableURLRequest alloc]initWithURL:bkMrkUrl];
[bkMrkReq setHTTPMethod:#"PUT"];
[bkMrkReq setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[bkMrkReq setHTTPBody:postData];
[NSURLConnection sendAsynchronousRequest:bkMrkReq queue:[NSOperationQueue currentQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSString *txt = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSLog(#"data....:%#",txt);
// handle response here
}];
Here, When i Print the text data
Output is: <?xml version="1.0" encoding="utf-8"?>
<result>CSRF validation failed</result>
What should i do with the data..
Here am updating the fields info in server.
You can try:
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"http://example.com/services/profiles/pid"]];
[request setHTTPMethod:#"PUT"];
NSString *params = #"\{\"pid\" : \"14997\", \"type\" : \"intervention\", \"uid\" : \"10046\"}"; // The rest of your parmas here
[request setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue currentQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
// handle response here
}];
If you want to make the request synchronously instead you can use:
NSURLResponse *response;
NSError *error;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
I'm having a hard time trying to receive JSON form a NSURLConnection request. Can anybody offer any advice? I can't understand why the JSON does not appear
EDIT: When I append the endpoint /books to the end of the url string I get this JSON response: " json NSDictionary * 0 key/value pairs. " Does this mean that there is nothing in the server?
-(void)makeLibraryRequests
{
NSURL *url = [NSURL URLWithString:#"http://prolific-interview.herokuapp.com/54bexxxxxxxxxxxxxxxxaa56"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; //;]cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:20.0f];
[request setHTTPMethod:#"GET"];
// This is actually how jQuery works. If you don't tell it what to do with the result, it uses the Content-type to detect what to do with it.
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
//[request setValue:#"application/json; charset=UTF-8" forHTTPHeaderField:#"Content-Type"];
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc]init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
//parse data here!!
NSError *jsonError;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonError];
if (json) {
//NSArray *allBooks = [json objectForKey:#"books"];
//create your MutableArray here
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
else{
NSLog(#"error occured %#", jsonError);
NSString *serverResponse = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSLog(#"\n\nError:\n%#\n\nServer Response:\n%#\n\nCrash:", jsonError.description, serverResponse);
//[NSException raise:#"Invalid Data" format:#"Unable to process web server response."];
}
}];
}
As YiPing pointed out, you must provide the books end point. But you won't have anything there until you first post a book.
NSDictionary *params = #{#"author": #"Diego Torres Milano",
#"categories" : #"android,testing",
#"title": #"Android Application Testing Guide",
#"publisher": #"Packt Publishing",
#"lastCheckedOutBy": #"Joe"};
NSURL *url = [NSURL URLWithString:#"http://prolific-interview.herokuapp.com/54bexxxxxxxxxxxxxaa56/books/"]; // your id removed for security's sake ... put it back in
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
NSError *encodeError;
NSData *body = [NSJSONSerialization dataWithJSONObject:params options:0 error:&encodeError];
NSAssert(body, #"JSON encode failed: %#", encodeError);
request.HTTPBody = body;
So, first POST a book using a request like the above, then your original GET (assuming you add the end point) will now return a result.
Add some endpoints to your URL
try this:
http://prolific-interview.herokuapp.com/54bexxxxxxxxxxxxxxxxaa56/books/
This question already has answers here:
Sending an HTTP POST request on iOS
(7 answers)
Closed 8 years ago.
How can i send data to server through URL using POST method.
My data is like below:
json == {
Signup = {
email = test;
password = 123;
username = test;
};
}
My URL is like this:
http://192.168.1.122/~test/sample/index.php/Api/signup
Please suggest me. I am stuck on this from last 2 days. Please help me.
Data format is JSON.
You could do something similar to send a simple post request with JSON Data
-(void)sendPostData{
NSString *urlStr = #"http://me.com";
urlStr = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:urlStr];
NSDictionary* info = [NSDictionary dictionaryWithObjectsAndKeys:user.userName,#"username",user.password,#"password",user.email,#"email", nil];
NSError *error;
NSData* bodyData = [NSJSONSerialization dataWithJSONObject:info
options:kNilOptions error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:data];
[request setValue:[NSString stringWithFormat:#"%d", [data length]] forHTTPHeaderField:#"Content-Length"];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *responseFromRequest, NSData *data, NSError *error)
{
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)responseFromRequest;
NSInteger code = [httpResponse statusCode];
}];
}
Have a look at my GitHub repo JWURLConnectionenter link description here, this will help you.
If you'r targeting an API I would also recommend JWRESTClient.