iPhone ile Web Service Kullanımı


iPhone uygulaması yazarken “Web Service” leri kullanmak isterseniz giriş niteliğinde kabul edilebilecek bu belgeyi kullanabilirsiniz.

Önce çalışan bir “Web Service” örneğine ihtiyacımız var. Asıl amaç “Web Service” yazmak olmadığından, elinizin altında da olmaması durumunda, birde bununla uğraşmamak için aşağıdaki örneği kullabilirsiniz. Bu dokümanın devamında bu örnek üzerinden anlatım yapılacaktır.

http://www.w3schools.com/webservices/tempconvert.asmx?op=CelsiusToFahrenheit

Bu adresi web tarayıcınıza yazdığınızda gelecek sayfada XML mesajlarını(sırasıyla request & response) görebilirsiniz. Öncelikle buradan “request” mesajını alıp koda yerleştirmekle işe başlayabilirsiniz.

webservice1

NSString *soapMessage = @"<?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"
			"<CelsiusToFahrenheit xmlns=\"http://tempuri.org/\">\n"
			"<Celsius>25</Celsius>\n"
			"</CelsiusToFahrenheit>\n"
			"</soap:Body>\n"
			"</soap:Envelope>\n";

XML datayı oluşturduktan sonra “Web Service URL” i ile bir URL objesi ve “request” oluşturmak gerekecek. Bu request için “HTTP Header” alanlarını tanımlayabilirsiniz.

“Content-Type”
“SOAPAction”
“Content-Length”

Bunları XML mesajının üzerinde bulabilirsiniz. “HTTP Method” ve “HTTP Body” yi de tanımladıtan sonra “request” i kullanarak bağlantıyı oluşturmaya başlayabilirsiniz.

webservice2

	NSURL *url = [NSURL URLWithString:@"http://www.w3schools.com/webservices/tempconvert.asmx?op=CelsiusToFahrenheit"];
 
	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://tempuri.org/CelsiusToFahrenheit" forHTTPHeaderField:@"SOAPAction"];
	[theRequest addValue: msgLength forHTTPHeaderField:@"Content-Length"];
	[theRequest setHTTPMethod:@"POST"];
	[theRequest setHTTPBody: [soapMessage dataUsingEncoding:NSUTF8StringEncoding]];
 
	NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];

Artık yapılması gereken bir bağlantı kurup, dönen XML cevabı parse etmek. Bağlantıyı “NSURLConnection” ile sağlıyoruz. Bağlantı sağladığında “NSURLConnection” in bazı methodlarını düzenlemek gerekmektedir. Dönen veriyi alabilmek için bu methodlar kullanılabilir. Cevabı “NSMutableData” objesine alarak, içinden istediğimiz değeri alabilirsiniz.

“NSURLConnection” methodları:

  • “didReceiveResponse” bağlantı kurulabiliyorsa çalışır. Bağlantı kurulabildiğini anladığımızda bizde Data’mızı sıfırlıyoruz.
  • “didReceiveData” herhangi bir data alınabildiğinde çalışır. Burada dönen datayı objenize alabilirsiniz.
  • “didFailWithError” ile herhangi bir hata durumunda “connection” ve “data” objelerini release etmek için uygun yer olacaktır.
  • Son method ise “connectionDidFinishLoading” bağlantı sona erdiğinde çalışacaktır. Burada dönen datadan bir xml metin oluşturabilir ve bu xml metni parse edebilirsiniz.
// Bağlantı kurulabiliyor mu?
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
	[webData setLength: 0];
}
// Dönen datayı alabileceğimiz method.
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
	[webData appendData:data];
}
// Bağlantıda herhangi bir hata olursa çalışacak method.
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
	NSLog(@"ERROR with theConnection");
	[connection release];
	[webData release];
}
// Bağlantı cevabı döndüğünde çalışan method. XML parse işlemini burada gerçekleştiriyoruz.
-(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];
}

“connectiondidFinishLoading” methodunda görebileceğiniz gibi dönüş değeri olan XML datayı NSXMLParser ile ayrıştırabilirsiniz. Bunu yapmak içinde NSXMLParser’ın methodlarını çağırmanız gerekmektedir:

  • “didStartElement” ile XML içindeki elementlerin başlangıcına bakıyoruz. Burada “CelsiusToFahrenheitResult” elementini arıyoruz. (recordResults = TRUE;)
  • “foundCharacters” elementin içindeki değeri eğer doğru element ise alacak method.
  • Son method elementin bitişine bakıyor. Burada aldğımız değeri ekrana yerleştirecek kod parçasını yazabilirsiniz.
// XML Element başlangıcı.
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *) namespaceURI qualifiedName:(NSString *)qName
attributes: (NSDictionary *)attributeDict
{
	if( [elementName isEqualToString:@"CelsiusToFahrenheitResult"])
	{
		if(!results)
		{
			results = [[NSMutableString alloc] init];
		}
		recordResults = TRUE;
	}
}
// Elementin içinde yazılı değer aldığımız method.
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
	if( recordResults )
	{
		[results appendString: string];
	}
}
// XML içinde .... ile Element bittiğinde aldığımız değeri ekranda bir component(Label, TextField vb.) içinde
// gösteriyoruz.
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
	if( [elementName isEqualToString:@"CelsiusToFahrenheitResult"])
	{
		recordResults = FALSE;
		myLabel.text = results;
		[results release];
		results = nil;
	}
}

“Web Service” örneğimiz dönüş değerini XML metni içinde isimli “Tag” ile vermekte. Bu değeri XML içinde alabilmek için yukarıda görüdüğümüz “didStartElement” ve “didEndElement” methodlarını yazdık. Start methodunda elementini gördüğümüz yerde bir “result” objesi oluşturuyor ve doğru elementi bulduğumuzu belirten bir sonuç değişkenine “TRUE” değerini atıyoruz. Sonra doğru elementte ise o elementin değerini “results(NSMutableString)” içine alıyoruz. En sonda ise “myLabel(UILabel)” üstüne yazdırıyoruz.

Bu yazıda geçen kavramlar ile ilgili ayrıntılı bilgi için aşağıdaki bağlantıları kullanabilirsiniz:

http://developer.apple.com/documentation/Cocoa/Conceptual/URLLoadingSystem/Tasks/UsingNSURLConnection.html
http://developer.apple.com/documentation/Cocoa/Conceptual/XMLParsing/XMLParsing.html
http://www.w3schools.com/soap/default.asp

No related posts.

Related posts brought to you by Yet Another Related Posts Plugin.

,

  1. #1 by gmakinabakan - April 14th, 2009 at 23:09

    Merhabalar,

    Cok faydali bir post olmus, tesekkurler. Ben de yazida gecen konuyla alakali bir iki sey eklemek istedim.

    - Tecrubelerime dayanarak soyleyebilirim ki iPhone icin mumkun oldugunca SOAP servislerden uzak durmak gerekiyor. (Bu yaziyi elestirmek icin soylemiyorum). Gelip giden headerlar ve datayi alma sekli performansi cok dusuruyor. SOAP servisleri yerine WCF(.NET icin) ve RESTfull API’lari kullanmak cok daha hizli. Yaptigimiz bir testte Flickr’in RESTfull API ile SOAP servisini kullandigimizda yaklasik 30% performans farki bulduk (Tabii bu Flickr’dan da kaynaklaniyor olabilir ama genelde kendini hissettiren bir yavaslik mevcut). Arka planda Entity Framework veya Azure (Cloud) kullaniyorsaniz tek yapmaniz gereken response’a object arraylerinizi serilaze etmek ve RESTfull XML’lerinizi iPhone’da parse etmek.

    - BIr diger alternatif de iPhone icin yazilmis herhangi bir JSON framework kullanarak server ile JSON objeleri araciligiyla konusmak. Boylece yukarida oldugu gibi event-based parsing yapmak zorunda kalmiyorsunuz. Ayrica birbirleri icinde yer alan objeleri (tree structure) de JSON framework otomatik olarak yaratiyor. Tek yapmaniz gereken servisinizden JSON gondermeniz ve aninda iPhone’da objeniz kullanima hazir:)

    BIliyorum yukaridaki yazi SOAP servislerine yonelikti ama ben de bir iki tecrubemi paylasmak istedim. Zaten bu forumun da amaci bu herhalde birbirimizden yararlanmak :) Herkese kolay gelsin :)

  2. #2 by Mustafa Tan - April 14th, 2009 at 23:30

    Kesinlikle ben de katılıyorum SOAP’tan uzak durmak gerektiğine ama bazen mecbur kalınıyor. Fakat bazen mecbur kalınıyor hazır sistemler sadece SOAP interface’i verince.

    Web servis kısmını da yazma imkanı varsa en güzeli ve en performanslısı belirttiğiniz gibi JSON.

  3. #3 by Kayhan Bölükbaş - April 15th, 2009 at 07:18

    Hemfikirim. Ama söylediği gibi mecbur kaldığımız zamanlar olabiliyor. Bu durumlarda da dikkatli ve özenli olmakta fayda var.

    Servisi kendimiz yazabiliyorsak, bende tamamen JSON tarafındayım :)
    Hatta böyle bir JSON kullanımına dair ipucu yazısı çıkar burdan :)

    Yorumlar için teşekkürler.

  4. #4 by Umut Gökbayrak - April 15th, 2009 at 08:01

    Hepimiz JSON formatını bu kadar çok seviyoruzken bu formatın mucidi sevgili Douglas Crockford abimizin 8. Linux ve Özgür Yazılım Şenliği için 17-18 Nisan 2009 tarihinde Bilgi Üniversitesi Dolapdere Kampüsünde olacağını da söylemek lazım gelir :)

  5. #5 by gmakinabakan - April 20th, 2009 at 03:54

    Benim size bir sorum olacak. Turkiye’deki iPhone yazilimcilari bir araya getiren bir forum var mi? Eger varsa iletirseniz cok sevinirim. Birbirimizden cok sey ogreniriz diye umit ediyorum. Ben birkac forum takip ediyorum ama orada ciddi yazilimcilardan daha cok iPhone kullanicilarina hitap eden tartismalar var. Onlar da maalesef bana cok katkida bulunamiyor. Simdiden tesekkurler. Herkese kolay gelsin.

  6. #6 by pcmuh - November 3rd, 2011 at 14:04

    merhabalar,şimdi ben bu makaledeki webservisi xcode ta nasıl kullanırım.Biraz yeniyim hangi sınıfta hangi kodları yazmak gerektiğini açıklarsanız sevinirim…

Yorum yazabilmeniz için giriş yapmış olmalısınız

  1. No trackbacks yet.