Solved webservices in IOS - how to

Posted on 2012-08-30
1 Endorsement
Last Modified: 2012-08-30
Hi, we’ve got a load of webservices that are running fine and provide data from our in house system.

We want to use these webservices on a native IPhone/Ipad app built using XCode and IOS 5.

I’ve been looking into how to consume the webservices on IOS and haven’t really found anything definitive, even putting in “IOS webservices” in amazon only returns 2 possible books….so I came back to EE and found this:

but the link from that page no longer works.

I understand that IOS doesn’t have inbuilt framework for working with SOAP, so you have to do it yourself.

So, what do people do in the real world? this is for a business app pulling data from our own system to a remote deice in one of our engineers hands.

As we’re a .net company, we’re obviously more at home with webservices, but what is the BEST solution for getting data to an IOS application from a remote server?
One article said that using an page with querystring parameters, outputting XML or JSON straight into the page response and reading that…. but that doesn’t sound a very “modern” solution.

Thanks in advance.
Question by:PatrickK_W
    LVL 14

    Accepted Solution

    Consuming a web service in iOS is much easier if you look this way:
    1- You have to create a request and send it to server (Obviously you have to conform to soap XML syntax)
    2- You will receive the response. The response will be in XML format so you have to parse it to get access to the data; hence you will use NSXMLParser or something else if you prefer.
    3- Parse and access the data.

    You can find useful resources here:
    Raywenderlich tutorial which uses ASI library to consume web service:

    2 years ago I wrote a class for my project which did the SOAP stuff for me (the web service was .asmx; I have attached it for you. Check .h file for usage -- You may customize it for your own use -- It may contain bugs since I did not spent much time for it.

    Actually the best solution for transferring data between a client and server depends on your project. If you need to have a consistent data transfer or the device has to connect to server frequently it's probably much better to implement socket connection between the two. If you plan to use socket connection approach you will have get extra benefits over the web service approach:
    - Parsing the data using sockets will be much easier on client side since you can define your own custom protocol
    - You transfer speed will be much higher using sockets
    - You have a big latency when you send a XML request since it's connectionless but in sockets you will have somehow a more uptime data transfer

    But you should notice, a server/client system which is based on web services is much more easier to implement; It's much easier to debug; It's more portable, you can integrate the web services easier in other platforms.

    //  soap.h
    //  splitview
    //  Created by Hamidreza Vakilian on 8/11/11.
    //  Copyright 2011 H.Vakilian. All rights reserved.
    // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Usage:
    //    SEL theSelector = @selector(mysoalcallback:);///Setting NSInvocation for the callback function to be called then
    //    NSMethodSignature *theSignature = [self methodSignatureForSelector:theSelector];
    //    NSInvocation *anInvocation = [NSInvocation invocationWithMethodSignature:theSignature];
    //    [anInvocation setSelector:theSelector];
    //    [anInvocation setTarget:self];
    //    soap *s = [[soap alloc] initWithWebServiceURL:@""];
    //    //you may use init but with the default URL set up in soap.m
    //    [s executeWebMethod:@"test" :nil :anInvocation];//calling the webmethod
    // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Call Back Function:
    //    -(void)mysoalcallback:(NSArray*) result
    //    {
    //        if(!result)
    //            NSLog(@"No Result!");///occurs for void webmethods
    //            else
    //            ////web method with results in result, do your job here
    //    }
    // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
    #import <Foundation/Foundation.h>
    @interface soap: NSObject <NSXMLParserDelegate> 
        NSMutableData *webData;
    	NSMutableString *soapResults;
    	NSXMLParser *xmlParser;
    	BOOL recordResults;
        NSInvocation *callbackfunction;
        NSString *_methodName;
        NSArray *_methodArguments;
        NSMutableArray *methodResultValues;
        NSMutableArray *methodResultNames;
        NSString* lastelement;
        NSString* parsed_chars;
        NSMutableString *webserviceurl;
    -(void) executeWebMethod:(NSString*)methodName:(NSArray*)methodArguments:(NSInvocation*)callback;
    @property (retain, nonatomic) NSString *_methodName;
    @property (retain, nonatomic) NSArray *_methodArguments;
    @property (retain, nonatomic) NSMutableString *webserviceurl;
    -(id)initWithWebServiceURL:(NSString*) url;

    Open in new window

    //  soap.m
    //  splitview
    //  Created by Hamidreza Vakilian on 8/11/11.
    //  Copyright 2011 __MyCompanyName__. All rights reserved.
    #import "soap.h"
    @implementation soap
    @synthesize _methodName, _methodArguments, webserviceurl;
    - (id)init
        self = [super init];
        if (self) {
            // Initialization code here.
            ////default webservice loacation for this project
            ////if you want to set another url use initWithWebServiceURL
            webserviceurl = [[NSMutableString alloc] initWithString:@""];
        return self;
    -(NSString*) createArgumentsTags:(NSArray*)arguments
        NSString *result = @"";
        for (int i = 0; i != [arguments count] ; i+=2) {
            result = [NSString stringWithFormat:
                      ,result, [arguments objectAtIndex:i], [arguments objectAtIndex:i+1], [arguments objectAtIndex:i] ];
        return  result;
    -(void) executeWebMethod:(NSString*)methodName:(NSArray*)methodArguments:(NSInvocation*)callback
            //This function executes the desired method from the corresponding webservice
            //      methodName: name of the method on the web service to call
            //      methodArguments: arguments of the method with this syntax:
            //                          arg1Name, arg1Value, arg2Name, arg2Value,...
            //      callback: the NSInvocation of the callback function that will be called when the method execution ends
        	recordResults = FALSE;
        callbackfunction = callback;
        methodResultValues = [[NSMutableArray alloc] init];
        methodResultNames = [[NSMutableArray alloc] init];
        lastelement = [[NSString alloc] init];
        parsed_chars = [[NSString alloc] init];
        self._methodName = methodName;
        self._methodArguments = methodArguments;
        NSString *soapMessage = [NSString stringWithFormat:
    							 @"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
    							 "<soap:Envelope xmlns:xsi=\"\" xmlns:xsd=\"\" xmlns:soap=\"\">\n"
    							 "<%@ xmlns=\"\">\n"
    							 "</soap:Envelope>\n", methodName, [self createArgumentsTags:methodArguments],methodName
    	NSURL *url = [NSURL URLWithString:self.webserviceurl];//@""
    	NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url];
    	NSString *msgLength = [NSString stringWithFormat:@"%d", [soapMessage length]];
    	[theRequest addValue: @"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
    	[theRequest addValue:[NSString stringWithFormat: @"", methodName] forHTTPHeaderField:@"SOAPAction"];
    	[theRequest addValue: msgLength forHTTPHeaderField:@"Content-Length"];
    	[theRequest setHTTPMethod:@"POST"];
    	[theRequest setHTTPBody: [soapMessage dataUsingEncoding:NSUTF8StringEncoding]];
    	NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
    	if( theConnection )
    		webData = [NSMutableData data];
    		NSLog(@"soap.m: theConnection is NULL");
    -(id)initWithWebServiceURL:(NSString*) url
        webserviceurl = [[NSMutableString alloc] initWithString:url];
        return  self;
    -(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(@"soap.m: ERROR with theConenction");
        if (callbackfunction) {
                [callbackfunction invoke];
    -(void)connectionDidFinishLoading:(NSURLConnection *)connection
    	NSLog(@"soap.m: DONE. Received Bytes: %d", [webData length]);
    	NSString *theXML = [[NSString alloc] initWithBytes: [webData mutableBytes] length:[webData length] encoding:NSUTF8StringEncoding];
    	xmlParser = [[NSXMLParser alloc] initWithData: webData];
    	[xmlParser setDelegate: self];
    	[xmlParser setShouldResolveExternalEntities: YES];
    	[xmlParser parse];
    -(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *) namespaceURI qualifiedName:(NSString *)qName
       attributes: (NSDictionary *)attributeDict
        parsed_chars = nil;
        lastelement = elementName;
    	if( [elementName isEqualToString:[NSString stringWithFormat: @"%@Result", self._methodName]])
    		recordResults = TRUE;
    -(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
    	if( recordResults )
            parsed_chars = string;
    -(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
        if( [elementName isEqualToString:lastelement] )
            if (parsed_chars) 
            [methodResultValues addObject: parsed_chars];
            [methodResultValues addObject: @""];            
            [methodResultNames addObject:lastelement];
    	if( [elementName isEqualToString:[NSString stringWithFormat: @"%@Result", self._methodName]])
    		recordResults = FALSE;
            [callbackfunction setArgument:&methodResultValues atIndex:2];
            [callbackfunction setArgument:&methodResultNames atIndex:3];
            [callbackfunction invoke];

    Open in new window

    LVL 1

    Author Comment

    That’s great thanks.
    The data is coming from a large SQL Server DB. The general idea is that the user gets their list of jobs daily, then updates the details of what they did on the iphone, then uploads the completion data back to the database.

    Of course that’s the simple outline – there are a lot of tables and data required to do this. the job itself is made up of multiple tables, and there are other entities, such as parts used, time spent, etc that is collected for the job.

    The data structure is quite complicated. Another question – and I’ll open another thread for this is – is it best to replicate the DB schema in SQLLite or “flatten” the strucuter as much as possible for SQLLite.
    LVL 1

    Author Closing Comment

    thanks for that. on the same idea, i've asked another question on a slightly different topic:

    about structuring complex data structures in SQLLite


    Featured Post

    Live: Real-Time Solutions, Start Here

    Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

    Join & Write a Comment

    There is a security feature on iOS devices that is nearly impenetrable when it has been activated.  This article will provide some possible solutions as well as necessary steps to take to ensure you do not end up with a locked device.
    It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
    This video discusses moving either the default database or any database to a new volume.

    746 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    19 Experts available now in Live!

    Get 1:1 Help Now