Main Contents

[Objective-c] iPhone et Webservices SOAP

juillet 19, 2009

Voilà un tutorial qu’on m’a souvent demandé. Nous allons voir comment réaliser une application qui va utiliser un WebService simple, envoyer un message SOAP, recevoir la réponse et la parser pour afficher le résultat.


Il va y avoir 4 étapes :

  • Creation du message SOAP
  • Envoie du message SOAP
  • Réception de la réponse
  • Parser la réponse et l’afficher

I) Le WebService

J’ai crée un petit Webservice qui attend une chaîne et qui renvoie « Hello votre-chaine ». Un simple « HelloWorld » en quelque sorte. Il est accessible à l’url : http://www.jkraft.fr/ws/serveur.php

II) Interface Builder

Première étape on crée notre interface graphique. On part d’un modèle « View-based-application », je l’ai appelé « Soap ». On ajoute 3 UILabel, un UITextField et un UIButton pour que ça ressemble à ça .

SoapInterface

III) Xcode

Ensuite on ajoute notre code dans SoapViewController.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@interface SoapViewController : UIViewController {
	IBOutlet UITextField *maSaisie;
	IBOutlet UILabel *monLabel;
	NSMutableData *webData;
	NSMutableString *soapResults;
	NSXMLParser *xmlParser;
	BOOL xmlResults;
}
 
@property(nonatomic, retain) IBOutlet UITextField *maSaisie;
@property(nonatomic, retain) IBOutlet UILabel *monLabel;
@property(nonatomic, retain) NSMutableData *webData;
@property(nonatomic, retain) NSMutableString *soapResults;
@property(nonatomic, retain) NSXMLParser *xmlParser;
 
-(IBAction)envoyer;
@end

On n’oublie pas de retourner dans Interface Builder pour lier le Label à son IBOutlet et notre bouton à son action.

Ensuite on attaque le gros morceau SoapViewController.m.

On ajoute les synthetize qui vont bien :

@synthesize maSaisie, monLabel, webData, soapResults, xmlParser;

Puis on s’occupe de la fonction envoyer. C’est elle qui va créer le message soap et l’envoyer au Webservice.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
-(IBAction)envoyer
{
	xmlResults = FALSE;
 
	NSString *soapMessage = [NSString stringWithFormat:
			@"<?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"
			 "<Hello xmlns=\"http://www.jkraft.com/\">\n"
			 "<nom>%@</nom>\n"
			 "</Hello>\n"
			 "</soap:Body>\n"
			 "</soap:Envelope>\n", maSaisie.text ];
	NSLog(soapMessage);
 
	NSURL *url = [NSURL URLWithString:@"http://www.jkraft.fr/ws/serveur.php"];
	NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url];
	NSString *msgLength = [NSString stringWithFormat:@"%d", [soapMessage length]];
 
	[theRequest addValue: @"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
	[theRequest addValue: @"http://www.jkraft.com/Hello" 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] retain];
	}
	else
	{
		NSLog(@"theConnection is NULL");
	}
	[maSaisie resignFirstResponder];
}

Donc on créer notre message Soap ligne 5. De la ligne 18 à 26 on prépare la connexion, en définissant l’url et très important en préparant les bonnes entêtes (Content-type, SOAPAction).
Ligne 27 on lance la connexion, attention au delegate=self il implique de gérer la connexion et ses retours.
C’est pour cela qu’on ajoute ces fonctions.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
-(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 theConkenction");
	[connection release];
	[webData release];
}
 
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
	NSLog(@"DONE. Received Bytes: %d", [webData length]);
	NSString *theXML = [[NSString alloc] initWithBytes: [webData mutableBytes] length:[webData length] encoding:NSUTF8StringEncoding];
	NSLog(theXML);
	[theXML release];
 
	if( xmlParser )
	{
		[xmlParser release];
	}
 
	xmlParser = [[NSXMLParser alloc] initWithData: webData];
	[xmlParser setDelegate: self];
	[xmlParser setShouldResolveExternalEntities: YES];
	[xmlParser parse];
 
	[connection release];
	[webData release];
}

Celle qui nous interesse le plus est connectionDidFinishLoading. Car une fois reçu la réponse, c’est ici qu’on va la traiter et dans notre cas parser le xml reçu.
Les lignes 21-22-23 ne servent que pour l’affichage dans les logs. Ligne 30 à 33 on parse notre réponse qui est webData. Attention encore une fois au [xmlParser setDelegate: self], il faut définir quelques fonctions supplémentaires qui font le boulot.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *) namespaceURI qualifiedName:(NSString *)qName
   attributes: (NSDictionary *)attributeDict
{
	if( [elementName isEqualToString:@"Result"])
	{
		if(!soapResults)
		{
			soapResults = [[NSMutableString alloc] init];
		}
		xmlResults = YES;
 
	}
}
 
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
	if( xmlResults )
	{
		[soapResults appendString: string];
	}
}
 
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
	if( [elementName isEqualToString:@"Result"])
	{
		xmlResults = FALSE;
		monLabel.text = soapResults;
		[soapResults release];
		soapResults = nil;
	}
}

La ça se complique un peu. C’est 3 fonctions ouvrent chaque balise XML (ligne 1 à 13) regarde le nom de la balise (ligne 15 à 21) et s’il correspond à celui recherché (ici c’est Result) alors elle sauvegarde le résultat (ligne 19) et l’affiche ( ligne 28).
Attention à la gestion de la mémoire, ne pas oublier de release les objets devenus inutiles.
On peut maintenant compiler et tester l’application. Dans les logs vous devriez voir l’appel et la réponse en XML, et le résultat s’afficher dans le label.

Result

Les sources sont téléchargeables : soap.zip

Catégorie(s): Développement, Iphone, Objective-C | Comments (19)

19 Comments

  1. greg (1 comments) août 27, 2009 @ 10 h 28 min

    exemple complet et fonctionnel, hyper bien expliqué et détaillé

    merci

  2. Adrien (1 comments) septembre 22, 2009 @ 20 h 05 min

    Joli Boulot ! Merci c’est très pédagogique…
    C’est exactement ce dont j’avais besoin !

    Si tu pouvais m’en dire plus sur ton petit webService (création-mise en place), tu serais génial !

  3. Mara Mbow (1 comments) septembre 23, 2009 @ 15 h 05 min

    Bonjour,
    je voudrais savoir ce que fait le fichier serveur.php

  4. francois (1 comments) novembre 9, 2009 @ 11 h 50 min

    Superbe exemple, simple et fonctionnel.
    Merci d’avoir laisser le webService qui va bien avec.
    Je dois passer un proxy pour accéder au web, peux tu m’aiguiller sur comme générer la ligne « proxy-authorisation: …. » dans le message Soap.

    Merci.

  5. Lotfi (1 comments) décembre 28, 2009 @ 4 h 36 min

    Excellent. Super bien expliqué. Ca serait très gentil de joindre la partie serveur en php

  6. Magicbob (1 comments) février 10, 2010 @ 15 h 17 min

    Clair, précis et efficace.

    Merci pour le boulot

  7. sunny22 (1 comments) février 20, 2010 @ 16 h 48 min

    Merci beaucoup pour ce tuto :)))
    Y a t il une possibilité d´avoir un exemple d´un formulaire écrit en objective C?
    Même une petite idée sur son code?
    Merci pour votre coopération

  8. Taleb (1 comments) avril 18, 2010 @ 17 h 17 min

    Bonjour, super tuto, les autres aussi sont bien expliqués.
    Je voulais savoir comment tu as fait pour la partie php, j’en ai besoin pour un projet que je dois finir dans 1 semaine.
    Toutes les autres réponses sont les bienvenues.
    Merci d’avance 🙂

  9. Safi (1 comments) mai 27, 2010 @ 14 h 22 min

    Bonjour, j’ai bien aimé le tuto et j’ai telechargé le code source et ça marche mais j’ai rencontré des problemes quand j’ai utilisé mon propre service en locale http://localhost:8080/axis2/services/helloWorld
    j’ai pas bien su manipuler le fichier xml peut etre donc j’ai besoin de votre aide

  10. Hoop (1 comments) juin 3, 2010 @ 16 h 11 min

    Bonjour, comme pour safi, j’ai voulu créer mon propre webservice avec axis2 mais j’ai du mal avec l’appel de ce dernier. Comment tu fais pour écrire le message SOAP en fonction du wsdl?
    Merci.

  11. Angad Soni (1 comments) juin 10, 2010 @ 12 h 56 min

    Hello Great tutorial thank you. For some reason i don’t get the result to show up what iphone simulator version are you running it in. I don’t get any error message either but i can’t get the result to show up…. Please help me Thank you…

  12. Arnaud Casella (2 comments) juillet 19, 2010 @ 11 h 20 min

    Oui, trop trop bien ton tutoriel, il manque juste la partie PHP pour qu’il soit parfait, comment pourrait-on la récupérer?

  13. Serveur WebService SOAP | MacFan juillet 19, 2010 @ 11 h 41 min

    […] [Objective-c] iPhone et Webservices SOAP […]

  14. baran (1 comments) décembre 12, 2010 @ 18 h 13 min

    thank you veru much for entry

  15. Sercan (1 comments) février 4, 2011 @ 6 h 51 min

    Hi,
    I have a problem with at the taking data from the web service. The problem is;
    in my web service i have a datasets and its own datatables. when i request the data at the dataset which has one data table i can read data, but when i request data from dataset which has many datatable i can not read the data, i think i should request exact datatable name from the dataset. But i cannot wrote this code. Please help me.

  16. Romain (6 comments) avril 29, 2012 @ 22 h 01 min

    Salut !

    Excellent mais comme bcp, j aurais bien aimé avoir des infos sur la partie serveur car actuellement c est la ou je bloque ! Creer le webservice qui va communiquer entre une BDD mysql et mon appli iPhone !!

    D avance merci

  17. sid (2 comments) octobre 5, 2012 @ 19 h 07 min

    Bonjour, j ‘ai une petite question je viens de faire la meme sur mon webservice mais j aimerai savoir est que la donnée est enregsitrer dans la BDD mysql d ailleur romain si jamais tu as debloquer je suis prenant merci encore pour ce tuto

  18. sid (2 comments) octobre 5, 2012 @ 20 h 22 min

    pourriez vous donnez lindication de ou recuperer toutes les autres données par exemple d une fonction get perso je les vois apparaitre dans le log mais apres comment les recuperer ?merci

  19. youness (1 comments) octobre 11, 2014 @ 16 h 53 min

    Merci exemple complet, est ce que je peut tester dans un pc Windows ? (j’ai pas Mac)

Leave a comment