Communicating with the outside world is one of the ways to make your iPhone applications interesting and useful. This is especially true today where they are so many web services that provide so much useful functionality.Xcode does not have built-in tools that make consuming web services easy. Everything must be done by hand and you need to know how to form the relevant XML messages to send to the web services and then parse the returning XML result.
Consuming Web Services
Here I took an example to parse a webservice which return Countries list.
This is the format for requesting the webservice called GetCountries from URL http://www.webservicex.net/country.asmx:
POST /country.asmx HTTP/1.1
Host: www.webservicex.net
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://www.webserviceX.NET/GetCountries"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetCountries xmlns="http://www.webserviceX.NET" />
</soap:Body>
</soap:Envelope>
- Create a NSObject Class with name "CountryParser" and write these lines of code in it
#import <Foundation/Foundation.h>
@interface CountryParser : NSObject <NSXMLParserDelegate> {
NSXMLParser *revParser;
NSMutableString *currentElement;
NSMutableArray *country;
}
-(NSMutableArray*)parseCountry:(NSString *)xml;
@end
- In .m file write these lines of code
#import "CountriesParser.h"
@implementation CountryParser
-(NSArray*) parseCountry:(NSString *)xml
{
country = [[NSMutableArray alloc] init];
xml = [xml stringByReplacingOccurrencesOfString:@">" withString:@">"];
xml = [xml stringByReplacingOccurrencesOfString:@"<" withString:@"<"];
NSData *data = [xml dataUsingEncoding:NSUTF8StringEncoding];
revParser = [[NSXMLParser alloc] initWithData:data];
[revParser setDelegate:self];
[revParser setShouldProcessNamespaces:NO];
[revParser setShouldReportNamespacePrefixes:NO];
[revParser setShouldResolveExternalEntities:NO];
[revParser parse];
[revParser release];
return country;
}
- (void)parserDidStartDocument:(NSXMLParser *)parser
{
}
- (void) parser: (NSXMLParser *) parser parseErrorOccurred: (NSError *) parseError {
}
//Calls when it finds the opening Tag
- (void) parser: (NSXMLParser *) parser didStartElement: (NSString *) elementName
namespaceURI: (NSString *) namespaceURI
qualifiedName: (NSString *) qName
attributes: (NSDictionary *) attributeDict{
}
//Calls and have value of particular Tag so here what we do recognize the tag and then retrieve its value
- (void) parser: (NSXMLParser *) parser didEndElement: (NSString *) elementName
namespaceURI: (NSString *) namespaceURI
qualifiedName: (NSString *) qName{
if([elementName isEqualToString:@"Name"])
[country addObject:currentElement];
// if you want something like adding value of element in dictionary and then when some closing tag comes then add this dictionary to array then here you can check that tag in if and write coding of adding here
[currentElement release];
currentElement = nil;
}
- (void) parser: (NSXMLParser *) parser foundCharacters: (NSString *) string{
if(!currentElement)
currentElement = [[NSMutableString alloc] initWithString:string];
else
[currentElement appendString:string];
}
-(void)dealloc
{
[super dealloc];
}
@end
- Now after creating these files we have half of our work done i.e. as we already create our Parser class which will parse our webservice now only thing left is to call the webservice which is to be parsed.
So to make call to the webservice GetCountries put following code in the class from where you need to call the webservice.
- But before calling webservice lets create another class which will check whether internet connection is available or not and will show error if internet connection is not available.
Create a NSObject class and named it Network (as it checks the network connection) and put following codes in it.
#import <Foundation/Foundation.h>
@interface Network : NSObject {
}
+(Boolean)checkNetwork;
@end
And in .m files put these lines of codes.
#import "Network.h"
@implementation Network
+(Boolean)checkNetwork
{
NSString *connected = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"http://www.google.com"] encoding:NSUTF8StringEncoding error:NULL];
if (connected == NULL)
{
return FALSE;
}else
{
return TRUE;
}
}
@end
- Now make a method "loadCountries()" which will make call to webservice.
#import <UIKit/UIKit.h>
@class MBProgressHUD;
@interface ConsumeWebServiceDemoViewController : UIViewController {
NSMutableData *dataWebService;
//for progerss status
MBProgressHUD *HUD;
}
@property (nonatomic, retain) MBProgressHUD *HUD;
-(void) LoadCountries;
-(IBAction)ButtonPressed;
@end
- This are those lines of code which will make call to webservice. It goes through the life cycle of NSURLConnection and make call asynchronously according to which different method will call.
#import "ConsumeWebServiceDemoViewController.h"
#import "Network.h"
#import "ConsumeWebServiceDemoAppDelegate.h"
#import "CountriesParser.h"
#import "CountriesViewController.h"
#import "MBProgressHUD.h"
@implementation ConsumeWebServiceDemoViewController
@synthesize HUD;
-(IBAction)ButtonPressed
{
[self LoadCountries];
}
-(void) LoadCountries
{
if (![Network checkNetwork]) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:@"Application requires Internet connection to Proceed."
delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
[alert release];
return;
}
HUD = [[MBProgressHUD showHUDAddedTo:self.view animated:YES] retain];
HUD.dimBackground = YES;
NSString *postString = @"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
"<soap:Body>\n"
"<GetCountries xmlns=\"http://www.webserviceX.NET\"/>\n"
"</soap:Body>\n"
"</soap:Envelope>";
dataWebService = [[NSMutableData data] retain];
NSURL *tempURL = [NSURL URLWithString:[NSString stringWithFormat:@"http://www.webservicex.net/country.asmx"]];
NSMutableURLRequest *request = [[NSMutableURLRequest requestWithURL:tempURL] retain];
NSString *postLength = [NSString stringWithFormat:@"%d", [postString length]];
[request addValue:@"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
[request addValue:@"http://www.webserviceX.NET/GetCountries" forHTTPHeaderField:@"SOAPAction"];
[request addValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]];
NSURLConnection * myConnection = [NSURLConnection connectionWithRequest:request delegate:self];
[myConnection start];
[request release];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[dataWebService setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[dataWebService appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSString *responseString=[[NSString alloc] initWithData:dataWebService encoding:NSUTF8StringEncoding];
CountriesParser *parser = [[CountriesParser alloc] init];
NSMutableArray *array=[parser parseCountries:responseString];
CountriesViewController *itemdetail=[[CountriesViewController alloc] initWithNibName:@"Countries" bundle:nil];
itemdetail.countries=[[NSArray alloc] initWithArray:array];
[self.navigationController pushViewController:itemdetail animated:YES];
itemdetail.modalTransitionStyle =UIModalTransitionStyleFlipHorizontal;
[itemdetail release];
[parser release];
[responseString release];
[dataWebService release];
[HUD hide:YES];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
}
-(void)viewDidLoad
{
[super viewDidLoad];
}
- (void)dealloc {
[HUD release];
[super dealloc];
}
@end
This is how you can consume webservice in our project. This is method of asynchronous call to webservice which will not stop responding Interface.
NOTE: The Hud file in this code will show the progressing of the webservice call which you can remove if you want.
(Please Find Attachment of Source code with the tutorial)
(Any Feedback will be appreciated)