Two Xcode examples, A Simple Calculator Example (Pure C) and A GeoIPService (C++) can be found in samples/ios.
#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.
#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.
#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_ios_settimeoutinterval(soap, 30.0); ... soap_end(soap); soap_destroy(soap);
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);
We assume you already have had the expereince in development of applications for iPhone and iPad using Xcode with iOS SDK installed.
The Xcode project for this example can be found in samples/ios/calc.
> wsdl2h -c -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. The option -c flags the wsdl2h tool to generate the service definition file in pure C. 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 -i -C calc.h
Option -C indicates client-side only files (soapcpp2 generates both client and server stubs and skeletons by default). This generates a number of soource files for client application development.
Figure 1. View of the Calculator Web Service Client
// File: CalcViewController.h #import <UIKit/UIKit.h> @interface CalcViewController : 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.
// File: main.m #import <UIKit/UIKit.h> #import "./Classes/calc.nsmap" int main(int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; int retVal = UIApplicationMain(argc, argv, nil, nil); [pool release]; return retVal; }
Then, implememt the source file CalcViewController.m as the following:
#import "CalcViewController.h" #import "soapStub.h" #import "gsoapios.h" @implementation CalcViewController @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_new(); if (soap_register_plugin(soap, soap_ios) == SOAP_OK) { // Specify the cache policy (optional) to NSURLRequestReturnCacheDataElseLoad // instead of NSURLRequestUseProtocolCachePolicy by deault soap_ios_setcachepolicy(soap, NSURLRequestReturnCacheDataElseLoad); // Specify the timeout interval (optional) to 45 seconds instead of // the default 60 seconds soap_ios_settimeoutinterval(soap, 45.0); 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 *tittleString; if (status == SOAP_OK) { resultString = [NSString stringWithFormat:@"%f",result]; tittleString = [NSString stringWithFormat:@"%f / %f =",x, y]; }else { resultString = [NSString stringWithFormat:@"%@",@"Soap fault!"]; tittleString = [NSString stringWithFormat:@"%@",@"Warning"]; } // Show the result in an alert UIAlertView *alert = [[UIAlertView alloc] initWithTitle:tittleString message:resultString delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; // Show the alert [alert release]; // Release the alert } else { // Caveat: Better to extract the error message and show it using an alert soap_print_fault(soap,stderr); // Print soap error in console } } soap_end(soap); // clean up allocated temporaries soap_free(soap); // Free soap context } ...
A screen snapshot of the client is shown in Figure 2.
Figure 2: Snapshot of the CalcViewService result
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
Devoplopment of he client appliation for this GeoIPService on iOS is similar to development for the cleant appliaction for A Simple Calculator Example (Pure C). The major dfferences are highlighted in following:
>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 -i -C -I$GSOAP_HOME/import GeoIPService.h
Option -i tells the compiler to generate C++ proxy and option -C 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.
Figure 3. View of the GeoIPService Client
// File: GeoIPServiceViewController.h #import <UIKit/UIKit.h> @interface GeoIPServiceViewController : UIViewController { UITextField *ipAddress; } @property (nonatomic, retain) IBOutlet UITextField *ipAddress; - (IBAction) buttonFindCountry:(id)sender; @end
Set the ipAddress outlet and the buttonFindCountry:(id)sender method to delegate action of the button.
The GeoIPServiceSoap12Proxy.h and GeoIPServiceSoap12Proxy.cpp are C++ proxy header and implementation files for SOAP 1.2 (You may use GeoIPServiceSoapProxy.cpp and GeoIPServiceSoapProxy.h for SOAP1.1).
// File: main.mm #import <UIKit/UIKit.h> #import "./Classes/GeoIPServiceSoap12.nsmap" int main(int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; int retVal = UIApplicationMain(argc, argv, nil, nil); [pool release]; return retVal; }
Then, implememt the source file GeoIPServiceViewController.m as the following:
#import "GeoIPServiceViewController.h" #include "soapGeoIPServiceSoap12Proxy.h" #import "gsoapios.h" using namespace std; typedef struct _ns1__GetGeoIP RequestStruct; typedef struct _ns1__GetGeoIPResponse ResponseStruct; @implementation GeoIPServiceViewController @synthesize ipAddress; - (IBAction)buttonFindCountry:(id)sender { RequestStruct ip; ResponseStruct response; GeoIPServiceSoap12Proxy service; std::string ipAdd = std::string((char *)[ipAddress.text UTF8String]); ip.IPAddress = &ipAdd; // ----- register plugin for callbacks ------ soap_register_plugin(&service, soap_ios); // Optional: timeout internal, the default is 60.0 seconds soap_ios_settimeoutinterval(&service, 30.0); // Optional: the default policy is NSURLRequestUseProtocolCachePolicy (0) soap_ios_setcachepolicy(&service, NSURLRequestReturnCacheDataElseLoad); // (2) int status = service.GetGeoIP(&ip, &response); string* result; string err_msg = "Invalid IP address"; if ( status == SOAP_OK) { if(response.GetGeoIPResult && response.GetGeoIPResult->CountryName) { result = response.GetGeoIPResult->CountryName; } else { result = &err_msg; } } else { service.soap_stream_fault(std::cerr); } NSString *soapResult; NSString *tittleMsg; if (status == SOAP_OK) { soapResult = [NSString stringWithUTF8String:result->c_str()]; tittleMsg = [NSString stringWithFormat: @"%@", @"Country Found"]; } else { soapResult = [NSString stringWithFormat: @"%@", @"Soap Error!"]; tittleMsg = [NSString stringWithFormat: @"%@", @"Warning"]; } UIAlertView *alert = [[UIAlertView alloc] initWithTitle:tittleMsg message:soapResult delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; [alert release]; service.destroy(); // Free soap context } ...
A screen snapshot of the client is shown in Figure 4.
Figure : Snapshot of the GeoIPServiceViewService result