current library for iOS to consume RESTful web service - ios

I have searched google for the different method and libraries used to consume a RESTful web service. But most of them are either outdated or failed to work when I tried the old libraries. This could be due to the fact that some of there were discontinued and not compatible with the new SDK.
I have tried SBJSON, ASIHTTP, stig's and jsonframework, but non of them seem to be working.
What are some of the current libraries that are being used in iOS to consume RESTful webservice? It will be helpful if anyone can give link to sample tutorial using the same libraries.

Try RestKit: http://restkit.org/
It is well known, popular, consumes XML as well as JSON and works with Core Data (response to NSManagedObjects mapping) which make great backend as a local cache.

Why dont you use iOS API classes like NSURLConnection? (iOS5 or above required I think)
You could invoke REST GET opperation for example like this:
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
[req setHTTPMethod:GET];
[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[url host]];//for https
connection = [[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:YES];
Where url should be an NSURL object pointing to your rest service operation url. And declare the corresponding delegate methods:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
code = [httpResponse statusCode];
NSLog(#"%# %i",#"Response Status Code: ",code);
[data setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)d {
[self.data appendData:d];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[[[UIAlertView alloc] initWithTitle:#"Error"
message:nil
delegate:nil
cancelButtonTitle:#"ok"
otherButtonTitles:nil] show];
self.connection = nil;
self.data = nil;
}
connection, data and code could be local variables to your implementation class. In those variables you are going to store the connection made, the JSON data received (or whatever) and the response http code like 200, 404.
And finally if you are planning to invoke a secured REST service, dont forget to include the authenticationchallenge delegate.
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
//set the user and password loged in
NSString *username = #"username";
NSString *password = #"password";
NSURLCredential *credential = [NSURLCredential credentialWithUser:username
password:password
persistence:NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
}
Hope this helps!

Use the built-in NSURLSession and NSJSONSerialization and then use Github's Mantle framework to map the JSON dictionary to your custom ObjC objects.

Related

Prestashop Search API Method in IOS Application

I'm building my first IOS Application and I'm currently integrating my application with my Prestashop website. I already have grabbed a ton of data from the databases, but I'm having less luck using the Search Method from their API.
I have successfully called the REST API and authenticated with the server. I'm getting back a response status code of 200 so everything looks ok with the authentication, however the data I'm receiving from the server is the homepage of my site in HTML form rather than an XML file with the search results.
Below I'll list some of the parts of code in question that I'm using to access the Prestashop server
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"https://www.******.com:443/api/search/?query=%#&language=1",searchTerm]];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];
This is the method I use to set up the connection to the Prestashop Server
-(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
{
NSLog(#"Test 1.5");
[self clearCookiesForURL];
if([challenge previousFailureCount]==0)
{
NSURLCredential *credential = [NSURLCredential credentialWithUser:#"(I'm omitting the credential key but it does work)" password:#"" persistence:NSURLCredentialPersistenceForSession];
NSLog(#"Credential : %#",credential);
//NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
[challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
} else{
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
}
And this is the method for my authentication. I have all of the other connection methods instantiated (canAuthenticateAgainstProtectionSpace, didReceiveResponse, didReceiveData, etc.) and they are all being called and working fine.
NSLog(#"Data After : %#",responseData);
NSString *tempString;
tempString = [[NSString alloc] initWithData:responseData encoding:NSASCIIStringEncoding];
NSLog(#"String : %#",tempString);
This is the section of code I use to translate the data I get from the server into a string (which i thought was going to be XML but is instead HTML)
Here is a screenshot of the debug log showing that I'm getting an HTML File
Can anybody see what I'm doing wrong here? Any help would be greatly appreciated!

HTTP(S) POST : connectionDidFinishLoading gets called with empty data, possible trust issue

I am trying to communicate with TSYS payment gateway which has an https server from my iOS application. My original code is given below.
-(void)postRequest:(NSString *)jsonBody{
NSData *requestData = [NSData dataWithBytes:[jsonBody UTF8String]
length:[jsonBody length]];
NSURL *url = [NSURL URLWithString:TSYS_URL];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:[NSString stringWithFormat:#"%d",[requestData length]]
forHTTPHeaderField:#"Content-Length"];
[request setValue:#"*/*" forHTTPHeaderField:#"Accept"];
[request setHTTPBody:requestData];
[[NSURLConnection alloc]initCustomURLWithRequest:request delegate:self ];
}
- (void)connection:(NSURLConnection *)connection
didReceiveResponse:(NSURLResponse *)response{
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
int code = [httpResponse statusCode];
NSLog(#"http error code : %d", code);
[self.receivedData setLength:0];
}
- (void)connection:(NSURLConnection *)connection
didReceiveData:(NSData *)data {
[self.receivedData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(#"receivedData.length : %d", [self.receivedData length]);
connection = nil;
}
- (void)connection:(NSURLConnection *)connection
didFailWithError:(NSError *)error {
connection = nil;
}
The payment gateway url is
#define TSYS_URL #"https://stagegw.transnox.com/servlets/TransNox_API_Server"
And I get this in console
http error code : 404
receivedData.length : 0
When I saw the log, the first port of call was about HTTPS SSL authentication, so I wrote a android project that do POST by trusting all certificate (not ideal, I know), and hurray I was getting correct response. But when I removed the part that enables HttpClient to trust all certificates, I got empty response(in Android).
To make iOS trust all certificate, I added below code
- (BOOL)connection:(NSURLConnection *)connection
canAuthenticateAgainstProtectionSpace:
(NSURLProtectionSpace *)protectionSpace {
//This always returns true
return [protectionSpace.authenticationMethod
isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection
didReceiveAuthenticationChallenge:
(NSURLAuthenticationChallenge *)challenge {
if([challenge.protectionSpace.authenticationMethod
isEqualToString:NSURLAuthenticationMethodServerTrust]){
NSURLCredential *credential = [NSURLCredential
credentialForTrust:challenge.protectionSpace.serverTrust];
[challenge.sender useCredential:credential
forAuthenticationChallenge:challenge];
}
[challenge.sender
continueWithoutCredentialForAuthenticationChallenge:challenge];
}
Still I get the same error.
Ok my questions are
First and foremost, why is this not working? I need to get this
working , so that I can move forward with project. Since my project
is in beginning state, I don't mind if the solution is to trust all
certificates. I somehow need to get server talking.
The type of authentication challenge I am getting is
NSURLAuthenticationMethodServerTrust. Ideally I should get the
server issued certificate and make my NSURLConnection object trust
it. How could I get the certificate file from server?
I got it working at last. In the end, it was not an issue with authentication. Along with the all the code above, I had to pass a header field "User-Agent" with the request. When I passed it I started to get response from the server.

NSURLConnection not logging to the console

I'm trying to get XML from a page, but the NSURLConnection is not returning anything.
- (void)downloadDataWithMission:(NSString *)mission
{
// Create a new data container for the stuff that comes back from the service
xmlData = [[NSMutableData alloc] init];
// Construct a URL that will ask the service for what you want
NSString *urlstring = [NSString stringWithFormat:#"http://www.google.com/"];
// , mission, [self getCountry]
NSURL *url = [NSURL URLWithString:urlstring];
// Put that URL into an NSURLRequest
NSURLRequest *req = [NSURLRequest requestWithURL:url];
// Create a connection that will exchange this request for data from the URL
urlConnection = [[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:YES];
}
# pragma mark NSURLConnection
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
// This method is called when the server has determined that it
// has enough information to create the NSURLResponse.
// It can be called multiple times, for example in the case of a
// redirect, so each time we reset the data.
// receivedData is an instance variable declared elsewhere
[xmlData setLength:0];
}
// This method will be called several times as the data arrives
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// Add the incoming chunk of data to the container we are keeping
// The data always come in the correct order
[xmlData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// We are just checking to make sure we are getting the XML
NSString *xmlCheck = [[NSString alloc] initWithData:xmlData encoding:NSUTF8StringEncoding];
NSLog(#"xmlCheck = %#", xmlCheck);
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
// Release the connection object, we're done with it
urlConnection = nil;
// Release the xmlData object, we're done with it
xmlData = nil;
// Grab the description of the error object passed to us
NSString *errorString = [NSString stringWithFormat:#"Connection Failed: %#", [error localizedDescription]];
// Create and show an alreat view with this error displayed
UIAlertView *av = [[UIAlertView alloc] initWithTitle:#"Error" message:errorString delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[av show];
}
#end
Why is the connection not working? Is this a problem in the delegate? In another project, all worked fine. The base SDK was the same in those projects - iOS 6.1.
Everything up to this line works perfectly:
NSString *xmlCheck = [[NSString alloc] initWithData:xmlData encoding:NSUTF8StringEncoding];
However it does not handle the encoding I think. Maybe there is sone invalid UTF-8 char at google. Try NSASCIIStringEncoding instead and it will work. If you want to use UTF-8 you might need to dig into why google is not UTF-8 compliant.

Basic auth iOS 6 - Not working

I am trying create a login screen which sends login info sharepoint server and i expect to be able to successfully login.
There are plenty of old examples and libraries which I am not able to use. But after spending hours I found this link to have the crux of all
http://transoceanic.blogspot.com/2011/10/objective-c-basic-http-authorization.html
My code looks like this now:
- (void) startLogin {
NSURL *url = [NSURL URLWithString:#"http://site-url.com"];
NSString *loginString =(NSMutableString*)[NSString stringWithFormat:#"%#:%#",usernameTextField.text,passwordTextField.text];
NSData *encodedLoginData=[loginString dataUsingEncoding:NSASCIIStringEncoding];
NSString *authHeader=[NSString stringWithFormat:#"Basic %#", [encodedLoginData base64Encoding]];
NSURLRequest *request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:3.0];
// [request setValue:authHeader forKey:#"Authorization"];
[request setValue:authHeader forHTTPHeaderField:#"Authorization"];
[request setHTTPMethod:#"POST"];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
There are three issues:
the commented out line-code doesn't give any error but it crashes on that line(while debugging)
on [request setValue:authHeader forHTTPHeaderField:#"Authorization"]; i am getting error "No visible interface for NSURLRequest declares selector setHTTPHeaderField"
Also, I am getting warning - unused variable "connection" in last line. I am not sure how this whole thing works and any simple example or correction is appreciated.
I would also like to know if there are any other simple methods for basic auth.
UPDATE: Delegate methods
- (void)connection:(NSURLConnection *)connection
didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
// Access has failed two times...
if ([challenge previousFailureCount] > 1)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Authentication Error"
message:#"Too many unsuccessul login attempts."
delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
else
{
// Answer the challenge
NSURLCredential *cred = [[NSURLCredential alloc] initWithUser:#"admin" password:#"password"
persistence:NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:cred forAuthenticationChallenge:challenge];
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(#"Connection success.");
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"Connection failure.");
}
Change NSURLRequest to NSMutableURLRequest to access it's setValue:forHTTPHeaderField method, and add a HOST header as well if it's a shared web host.
At the end, you have to start the connection:
[connection start];
Also, make sure you've set up your NSURLConnectionDelegate delegate methods for the call backs.

polling an external server from an app when it is launched

I am new to iOS and working on an app which runs on a real device (iPad). So, when I launch my app on the iPad after the view is visible, the app should be able poll a web server or something (without any user interaction) and get some information over HTTP and based on this information, I want fill some text fields in the app view. can you let me know if it is possible to do something like this in iOS? if so how and some sample pieces of code would be much appreciated.
Thanks.
You can download information over http using NSURLConnection in the viewWillAppear or viewDidLoad. After download the data if its XML parse using NSXMLParser (or any other XML parser for iOS).
//Lets say you have download and process method
- (void)downloadAndProcess
{
//URL you want to download Info from
NSURL* url = [NSURL URLWithString:#"http://google.com"];
//Make a mutable url request
NSMutableURLRequest* req = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:60];
NSURLConnection* conn = [NSURLConnection connectionWithRequest:req delegate:self];
if(conn)
{
//NSMutableData receivedData is an instance variable
receivedData = [[NSMutableData alloc] init];
}
}
//NSURLConnection Delegate methods here
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[receivedData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[receivedData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"Error downloading data :%#",[error localizedDescription]);
// release receivedData object when connection fails
[receivedData release],receivedData = nil;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// Connection did finish downloading data which you can process based on what your data is
// release receivedData object once you are done processing it.
[receivedData release],receivedData = nil;
}

Resources