Friday, 12 April 2013

How to use web service in iOS app

In iOS apps you often need to use web services, today we will learn how to use web service in iOS app. Here we will learn a simple and basic use of web service( A SOAP base service ), in next post we will learn the use of RESTful web service.

What is a web service : A web service (ws) is a media where you request some information from the server and the server processes your request and provides you with the appropriate response.

The response can be in various formats like XML (Extensible mark up language), JSON (JavaScript Object Notation), CSV (comma separated value)
In this post we will send a SOAP request to the server 
and reading the output(response) which will be in xml  by using web service provided by w3schools. 
  Step 1 Create a new simple view project in xcode and make design of your project similar to following

Also make properties of required view and IBAction to connect with button.

In first text field we will give value of temperature in Celsius and output will be shown in 2nd text field after pressing button.

   Step 2 For making a call to the webservice running in some server you need to call that service via SOAP request, so to know whats the format of your soap request  check this link where your web method is and their you will get the list of appropriate methods that you may want to use so select the appropriate method, below given are the snaps that will help you out for the web method that I am using.

 Request and response page

Step 3: To execute a web method you need to first need to create the soap body format and pass some of the parameters that are required by that method, and that you can do with the help of the below line

NSString *soapFormat = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
                                    "<soap:Envelope xmlns:xsi=\"\" xmlns:xsd=\"\" xmlns:soap=\"\">\n"
                                    "<CelsiusToFahrenheit xmlns=\"\">\n"

Now we need to specify the location of the web method and that you can do with the help of the NSURL class 

NSURL *locationOfWebService = [NSURL URLWithString:@""];

Now we need to create a soap header  by using the class NSMutableURLRequest , remember soap body and soap header are two different things, don't mix these two.

NSMutableURLRequest *theRequest = [[NSMutableURLRequest alloc]initWithURL:locationOfWebService];
            NSString *msgLength = [NSString stringWithFormat:@"%d",[soapFormat length]];
            [theRequest addValue:@"text/xml" forHTTPHeaderField:@"Content-Type"];
            [theRequest addValue:@"" forHTTPHeaderField:@"SOAPAction"];
            [theRequest addValue:msgLength forHTTPHeaderField:@"Content-Length"];
            [theRequest setHTTPMethod:@"POST"];
            //the below encoding is used to send data over the net
            [theRequest setHTTPBody:[soapFormat dataUsingEncoding:NSUTF8StringEncoding]];

and finally we will check whether the connection is established or not by creating object of
NSURLConnection class.

NSURLConnection *connect = [[NSURLConnection alloc]initWithRequest:theRequest delegate:self];
            if (connect) {
                webData = [[NSMutableData alloc]init];
                NSLog(@"Connection Establish");
            else {
                NSLog(@"No Connection established");

In the above code I have took a member of NSMutableData and initialized it, this variable will have the entire xml structure that will be required by us to parse.

Step 4: The NSURLConnection class has delegate method that we must implement so that we can read the xml structure that is returned by the webservice, if you want to see the xml format of the webservice that is returned then it will be provided just below the soap request section.

The delegate methods of NSURLConnection that you will be using are 

didReceiveResponse: In this method you set the mutabledata’s length to zero so that the data present from any previous request is clear

didReceiveData: Append the mutabledata variable with the data received from the webservice

didFailWithError: If the internet connection crashes then write code inside this method to prompt a message to the user for connection failure.

connectionDidFinishLoading: You will be writing code inside this method once the loading of the xml output is done in the mutable data

Here is the code of these methods

#pragma - NSURLConnection delegate method

-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
    [webData setLength: 0];

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    [webData appendData:data];

-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
    NSLog(@"ERROR with theConenction");
    //[connection release];
    //[webData release];

-(void)connectionDidFinishLoading:(NSURLConnection *)connection
    NSLog(@"DONE. Received Bytes: %d", [webData length]);
    self.xmlParser = [[NSXMLParser alloc]initWithData:webData];
    [self.xmlParser setDelegate: self];
    //    [self.xmlParser setShouldProcessNamespaces:NO];
    //    [self.xmlParser setShouldReportNamespacePrefixes:NO];
    //    [self.xmlParser setShouldResolveExternalEntities:NO];
    [self.xmlParser parse];

Step 5: Now its time to parse the xml for this I have used the NSXMLParser, You may use any xml parser of your choice. In step 4 you can see I have allocated and initialized memory space for the parser and it has some delegate method that I have used to get the work done.

Here is the code of these methods.
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
    NSLog(@"found character %@",string);
    [nodeContent appendString:[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
    self.finaldata = nodeContent;
    _output.text = finaldata;
    NSLog(@"node %@",nodeContent);
    NSLog(@"final %@",finaldata);

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
    if ([elementName isEqualToString:@"CelsiusToFahrenheitResult"]) {
        self.finaldata = nodeContent;
        _output.text = finaldata;
        NSLog(@"did End Element");
    _output.text = finaldata;

- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError{

Now run the code out put will be look like this

Download source code from this  link
Remember I used xcode 4.6

1 comment: