Genivia Home Documentation
The iOS plugin for developing client applications on iOS (iPhone and iPad) platforms

updated Tue Aug 9 2016
 
The iOS plugin for developing client applications on iOS (iPhone and iPad) platforms

Introduction

Consuming Web services on iOS (iPhone and iPad) platforms is inreseasingly in demand today. However, Xcode does not have any built-in tools that make consuming Web services easy. It typically requires knowledge of XML processing techniques to send soap requests to the Web services and then parse the returning XML results. The gSOAP toolkit that provides an automated SOAP and XML data binding for C and C++ can be used directly to develop client applications to consuming Web services on iOS platforms such as iPhone and iPad. However, it's default network connection does not leverage the advantages of network connection offered by iOS SDK, instead it uses lower level TCP sockets for network connection. This soap plugin facilitates developers to develop Web services client applications on iOS platforms without maniulating the XML processing. Moreover, it takes andvantages of network connection offered by iOS SDK and supports 3G/4G, wifi etc.

Four Xcode examples, A Simple Calculator Example (Pure C) and A GeoIPService (C++) can be found in samples/ios.

Getting Started

To start building Web services client applications for iPhone and/or iPad with gSOAP , you need:

Development of Web services applications on iOS is no different from the development SOAP Web services applications on Linux, Unix and Mac OS except with a soap plugin registration. Specifically, there are four steps to develop SOAP Web services client applications on iOS:

Registering iOS Plugin (Required)

To register the iOS plugin, simply call soap_register_plugin method:

#import "gsoapios.h"
struct soap *soap = soap_new();
soap_register(soap, soap_ios); // Register the iOS plugin
...
soap_end(soap); // Clean up temporaries
soap_destroy(soap); // Free soap context

The plugin is destroyed automatically by the soap context when the soap_end method is executed.

Specifying Cache policy (Optional)

The interaction beween the client and the Web servcie server can be controled by specifying the cache policy. To specify the cache policy, call the method soap_ios_setcachepolicy(struct soap *soap, unsigned int policy) . The method cannot be called before the pluging is registered.

#import "gsoapios.h"
struct soap *soap = soap_new();
soap_register(soap, soap_ios); // Register the iOS plugin
// Specify the cache policy for the request
// Caveat: this method cannot be called before the plugin is registered
// If this method is not called, the cache policy is set to NSURLRequestUseProtocolCachePolicy (0) by default.
soap_ios_setchacepolicy(soap, NSURLRequestReturnCacheDataElseLoad); // (2)
// Or use the integer directly instead of enum
// soap_ios_setchacepolicy(soap, 2); // (NSURLRequestReturnCacheDataElseLoad)
...
soap_end(soap); // clean up allocated temporaries
soap_destroy(soap); // Free soap context

The available cache policies that can be specified are:

enum {
NSURLRequestUseProtocolCachePolicy = 0,
NSURLRequestReloadIgnoringLocalCacheData = 1,
NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData,
NSURLRequestReturnCacheDataElseLoad = 2,
NSURLRequestReturnCacheDataDontLoad = 3,
NSURLRequestReloadIgnoringLocalAndRemoteCacheData =4,
NSURLRequestReloadRevalidatingCacheData = 5
}

If this method is not called, the cache policy is set to NSURLRequestUseProtocolCachePolicy (0) by default.

Specifying Timeout Interval (Optional)

The timeout interval for network connection can be specified using the method soap_ios_settimeoutinterval(struct soap *soap, double seconds). The method cannot be called before the pluging is registered. If this method is not called, the timeout interval is 60 seconds by default.

#import "gsoapios.h"
struct soap *soap = soap_new();
soap_register(soap, soap_ios); // Register the iOS plugin
// Specify the timout interval in terms of seconds
// If this method is not called, the timeout interval is set to 60 seconds by default
// Caveat: this method cannot be called before the plugin is registered
...
soap_end(soap);
soap_destroy(soap);

Handling HTTP Authentication

A server may request user authentication and deny access (HTTP 401 error) when the client tries to connect without HTTP authentication (or with the wrong authentication information).

HTTP authentication (basic) is enabled at the client-side by setting the soap.userid and soap.passwd strings to a username and password, respectively.

Be aware of that both of userid and password must be set in pair, that is, if one of them is set, the other must be set too.

If the server requires basic HTTP authentication, for example, the userid and password can be specified:

struct soap *soap = soap_new();
soap->userid = "someone";
soap->passwd = "somepass";
...
soap_end(soap); // Clean up temporaries
soap_destroy(soap);

Examples

This section intoduces two examples to demonstrate the development of client applications consuming SOAP Web services on iOS platforms (iPhone and iPad) using gSOAP tools and the iOS plugin. Because gSOAP supports development for both pure C and C++, the first example, A Simple Calculator Example (Pure C), is developed using pure C. The second one, A GeoIPService (C++), is developmed using C++.

We assume you already have had the expereince in development of applications for iPhone and iPad using Xcode with iOS SDK installed.

It is crucial to follow these directions in order for your app to work:

A Simple Calculator Example (Pure C)

This example shows you how to develop a client application in C using gSOAP and the ios plugin, which consumes a simple caculator service on iOS using gSOAP. The simple calculator service was developed and deployed as a demo using the gSOAP tools (refer to http://www.genivia.com/Products/gsoap/demos/index.html for details). The gSOAP Calculator Service provides several operations such as add, sub, mul, div etc. In this example, we use operation add as a demo. Other operations are alled in a similar way. The wsdl file for this service can be obtained at the following link: http://www.genivia.com/calc.wsdl

The Xcode project for this example can be found in samples/ios/calc.

Step 1: Generating stubs for C API

To generate codes for the calculator Web service, we first run the wsdl2h tool from the command line on the URL of the WSDL and use option -o to specify the output file (Alternatively, you can download the calc.wsdl and use the local file instead of the URL):

> wsdl2h -o calc.h http://www.genivia.com/calc.wsdl

This generates the calc.h service definition header file with service operation definitions and types for the operation's data. By default, gSOAP assumes you will use C++ with STL.

We have not yet generated the stubs for the CAPI. To do so, run the soapcpp2 compiler:

> soapcpp2 -j -CL -I /path/to/import calc.h

Option -CL indicates client-side only files (soapcpp2 generates both client and server stubs and skeletons by default). This generates a number of source files for client application development.

Step 2: Creating Xcode project for iPhone

Launch the Xcode, create a View-based Application project and name it Calc. Open the CalcViewController.xib file in the Interface Builder. Double-click on the View item and populate it with the views listed below and shown in Figure 1:

calc-view.png
Figure 1. View of the Calculator Web Service Client

In Xcode, edit the file CalcViewController.h to make it look like the following:

// File: CalcViewController.h
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController {
UITextField *op1; // operand1
UITextField *op2; // operand2
}
@property (nonatomic, retain) IBOutlet UITextField *op1;
@property (nonatomic, retain) IBOutlet UITextField *op2;
- (IBAction) buttonPressed;
@end

Link the op1 and op2 to the two Text Fields and delegate the button action to method buttonPressed.

Step 3: Adding generated source stubs to the Xcode project

Add the source files soapC.cpp, soapClient.cpp, soapH.h, and soapStub.h generated in Step 1: Generating stubs for C API to the project. Also add files stdsoap2.h and stdsoap2.cpp to the project from gsoap package as well as the iOS pluhin files gsoapios.h and sgsoapios.mm.

Once all of your files have been added to the project, ensure they are all of type "Objective C++ Source". This ensures that there will be no issues with mixing Objective C and C++ code.

In Xcode, edit the file info.plist to make it look like the following:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
@end code
These changes ensure that you cna access the web services despite the added layer of protection.
@subsubsection ios_calc_step_4 Step 4: Implementing the Logic by calling the soap service
Firstly, edit file <i>main.mm</i> to import the file <i>./Classes/calc.nsmap</i>.
Link errors may arise without importing this namespace mapping.
@code
// File: main.mm
#import <UIKit/UIKit.h>
#import "../../calc.nsmap"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));}
}

Then, implememt the source file CalcViewController.mm as the following:

//
// ViewController.mm
// calc
//
// Created by Bethany Sanders on 7/11/16.
// Copyright © 2016 Bethany Sanders. All rights reserved.
//
#import "ViewController.h"
#import "soapStub.h"
#import "gsoapios.h"
@implementation ViewController
@synthesize op1; // Set or get opreand1
@synthesize op2; // Set or get opreand1
- (IBAction) buttonPressed
{
double x = [op1.text doubleValue];
double y = [op2.text doubleValue];
struct soap *soap = soap_new1(SOAP_IO_DEFAULT|SOAP_IO_KEEPALIVE|SOAP_XML_INDENT|SOAP_XML_STRICT);
if (soap_register_plugin(soap, soap_ios) == SOAP_OK) {
// Specify the timeout interval (optional) to 45 seconds instead of
// the default 60 seconds
double result;
// Call Web service operation add
int status = soap_call_ns2__add(soap, NULL, NULL,x, y, result);
soap_free_temp(soap); // Cleanup temporary resources
// Check soap response status
if (status == SOAP_OK) {
NSString *resultString;
NSString *titleString;
resultString = [NSString stringWithFormat:@"%f",result];
titleString = [NSString stringWithFormat:@"%f + %f =",x, y];
// Show the result in an alert
UIAlertController * alert = [UIAlertController
alertControllerWithTitle:titleString
message:resultString
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* cancelButton = [UIAlertAction
actionWithTitle:@"OK"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action){}];
[alert addAction: cancelButton];
[self presentViewController:alert animated:YES completion:nil];
}
else
soap_print_fault(soap,stderr); // Print soap error in console
}
soap_destroy(soap); //free soap
}
@end

A screen snapshot of the client is shown in Figure 2.

calc-result.png
Figure 2: Snapshot of the CalcViewService result

A GeoIPService (C++)

GeoIPService is a live SOAP Web service that enables you to look up contries by IP address or by Context.

This example shows you how to develop a client application in C++ using gSOAP and the ios plugin, which consumes the GeoIPSerive on iOS using gSOAP. The WSDL file for this servive can be downloaded at the following link: http://www.webservicex.net/geoipservice.asmx?WSDL

It is crucial to follow these directions in order for your app to work:

The Xcode project for this example can be found in samples/ios/GeoIPService.

Step 1: Generating stubs for C++ Proxy

To generate codes for the GeoIPSerbice Web service, we first run the wsdl2h tool from the command line on the URL of the WSDL and use option -o to specify the output file (Alternatively, you can download the GeoIPService.wsdl file and use the local file instead of the URL):

>wsdl2h -o GeoIPService.h http://www.webservicex.net/geoipservice.asmx?WSDL

This generates the GeoIPService.h service definition header file with service operation definitions and types for the operation's data. By default, gSOAP assumes you will use C++ with STL.

To generate the stubs for the C++ proxy classes, run the soapcpp2 compiler:

>soapcpp2 -j -CL -I$GSOAP_HOME/import GeoIPService.h

Option -j tells the compiler to generate C++ proxy and option -CL indicates client-side only files (soapcpp2 generates both client and server stubs and skeletons by default). Option -I is needed to import the stlvector.h file from the import directory in the gSOAP package to support serialization of STL vectors.

Step 2: Creating Xcode project for iPhone

Create a View-based Application project and name it GeoIPService and rename the .m source files to .mm. Open the GeoIPserviceViewController.xib file in the Interface Builder. Double-click on the View item and populate it with the views listed below and shown in Figure 3:

geoip-view.png
Figure 3. View of the GeoIPService Client

In Xcode, edit the file GeoIPServiceViewController.h to make it look like the following:

// File: GeoIPServiceViewController.h
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController{
UITextField* IPAddress;
}
@property (strong, nonatomic) IBOutlet UITextField *IPAddress;
- (IBAction) buttonPressed;
@end

Set the ipAddress outlet and the buttonFindCountry:(id)sender method to delegate action of the button.

In Xcode, edit the file info.plist to make it look like the following:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
@end code
These changes ensure that you cna access the web services despite the added layer of protection.
@subsubsection ios_geoip_step_3 Step 3: Adding generated source stubs to the Xcode project
Add the source files <i>soapC.cpp</i>, <i>GeoIPServiceSoap12Proxy.cpp</i>,
<i>GeoIPServiceSoap12Proxy.h</i>, <i>soapH.h</i>,
and<i>soapStub.h</i> generated in @ref ios_geoip_step_1 to the project. Also
add files<i>stdsoap2.h</i> and <i>stdsoap2.cpp</i> to the project from gsoap
package and the iOS pluhin files <i>gsoapios.h</i> and <i>sgsoapios.m</i>.
Do not forget to rename the <i>sgsoapios.m</i> to <i>sgsoapios.mm</i>
The <i>GeoIPServiceSoap12Proxy.h</i> and <i>GeoIPServiceSoap12Proxy.cpp</i>
are C++ proxy header and implementation files for SOAP 1.2 (You may use
<i>GeoIPServiceSoapProxy.cpp</i> and <i>GeoIPServiceSoapProxy.h</i>
for SOAP1.1).
@subsubsection ios_geoip_step_4 Step 4: Implementing the Logic by calling the soap service
Firstly, edit file <i>main.mm</i> to import the file
<i>./Classes/GeoIPService.nsmap</i>. Link errors would arise without importing
this namespace mapping.
@code
// File: main.mm
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#include "../../GeoIPServiceSoap.nsmap"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));}
}
}

Then, implememt the source file GeoIPServiceViewController.mm as the following:

ViewController.mm calc

Created by Bethany Sanders on 7/11/16. Copyright © 2016 Bethany Sanders. All rights reserved.

#import "ViewController.h" #include "soapGeoIPServiceSoapProxy.h" #import "soapStub.h" #import "gsoapios.h" using namespace std;