iPhone app crash while application one thread running async - iphone

I am currently working in small chat app in iPhone. I am call to web services; one for data sending, and other for get friends response. I am implementing the code as follows:
NSMutableData *webData;
NSXMLParser *xmlParser;
NSMutableString *xmlParsingResult;
NStimer *timer;
-(IBAction)send:(id)sender
{
//req include web request info
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];
if (conn)
{
webData = [[NSMutableData data] retain];
}
}
-(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
{
[connection release];
[webData release];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
xmlParser = [[NSXMLParser alloc] initWithData: webData];
[xmlParser setDelegate: self];
[xmlParser setShouldResolveExternalEntities: YES];
[xmlParser parse];
[xmlParser release];
[connection release];
[webData release];
}
-(void)parser:(NSXMLParser *)xmlparser didStartElement:(NSString *)elementName namespaceURI:(NSString *) namespaceURI qualifiedName:(NSString *)qName attributes: (NSDictionary *)attributeDict
{
if( [elementName isEqualToString:#"string"])
{
if(!xmlParsingResult)
{
xmlParsingResult = [[NSMutableString alloc] init] ;
}
}
}
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
[xmlParsingResult appendString: string];
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if( [elementName isEqualToString:#"string"])
{
if(timer!=nil)
{
}
else
{
[self performSelectorInBackground:#selector(CallResponse) withObject:nil];
}
xmlParsingResult=nil;
[xmlParsingResult release];
}
}
//==================================================================================================================
-(void)CallResponse
{
NSLog(#"timer start:");
NSAutoreleasePool *timerNSPool = [[NSAutoreleasePool alloc] init];
timer = [NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:#selector(Refresh:) userInfo:nil repeats: YES];
NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
[runLoop run];
[timerNSPool release];
}
-(void)Refresh:(NSTimer *)TimeVal
{
// call web service to get response
// if error occur then timer will be release and nil
}
My app crashes and it throws the following error:
bool _WebTryThreadLock(bool), 0x7089e20: Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now...
How can I debug why this happens?

THe error message tells you exactly what the problem is. For what it's worth, there's no need to create a background thread and run loop just to start an NSTimer. You may as well just create the NSTimer in your main thread—it won't block it, it'll just sit in the run loop and fire when it needs to. There's no need for -performSelectorInBackground:withObject:.

Related

How can i Parse this xml using NSXMLParser in ios?

<root>
<table name="radios">
<column name="nameradio">Radio1</column>
<column name="logo">http://app.syndicationradio.fr/demo/logo1.png</column>
<column name="stream">http://cloud2.syndicationradio.fr:8020</column>
<column name="twitter">http://www.twitter.com/#syndicationradio</column>
<column name="facebook">http://www.facebook.com/syndicationradio</column>
<column name="titre">http://app.syndicationradio.fr/demo/title.xml</column>
</table>
<table name="radios">
<column name="nameradio">Radio2</column>
<column name="logo">http://app.syndicationradio.fr/demo/logo1.png</column>
<column name="stream">http://cloud2.syndicationradio.fr:8020</column>
<column name="twitter">http://www.twitter.com/#syndicationradio</column>
<column name="facebook">http://www.facebook.com/syndicationradio</column>
<column name="titre">http://app.syndicationradio.fr/demo/title.xml</column>
</table>
</root>
Now please is there anybody help to find out that, how can i get those url from the xml data using NSXMLParser or any other xml parser suppose TBXML in IOS?
Edit: you can also give me example of libxml parser for this xml.
Thanks In Advance.
Try this:
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *url = [[NSURL alloc] initWithString:#"yourURL"];
NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
[parser setDelegate:self];
BOOL result = [parser parse];
// Do whatever with the result
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict {
NSLog(#"Did start element");
if ([elementName isEqualToString:#"root"]) {
NSLog(#"found rootElement");
return;
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
NSLog(#"Did end element");
if ([elementName isEqualToString:#"root"]) {
NSLog(#"rootelement end");
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
NSString *tagName = #"column";
if ([tagName isEqualToString:#"column"]) {
NSLog(#"Value %#",string);
}
}
Ok you asked for a libxml example. I used it in a project but with TBXML instead of NSXMLParser because this one caused important problems of encoding and data retrieving.
First you have to download TBXML.m and TBXML.h files from the web and import them into your project. Then you also have to link libxml2.dylib to your project in Link Binary with Libraries.
Once this done, you will have to do this to retrieve your data (based on your XML source) :
NSData *xmlData = [NSData dataWithContentsOfURL:yourURL];
TBXML *tbxml = [TBXML newTBXMLWithXMLData:data error:nil];
[self getData:tbxml.rootXMLElement];
- (void) getData : (TBXMLElement *) element
{
do {
if([[TBXML elementName:element] isEqualToString:#"table"])
{
if([[TBXML elementName:element] isEqualToString:#"column"])
{
if([[TBXML attributeName:element] isEqualToString:#"nameradio"])
{
// You decide what to do here
}
}
}
if (element->firstChild) [self getData:element->firstChild];
} while(element = element->nextSibling);
}
You probably will have to change this code but here you have all the basic things you need.
This is how you can use NSXMLParser :
In your .h file declare :
NSMutableData *webPortFolio;
NSMutableString *soapResultsPortFolio;
NSURLConnection *conn;
//---xml parsing---
NSXMLParser *xmlParserPortFolio;
BOOL elementFoundPortFolio;
NSMutableURLRequest *req;
NSString *theXMLPortFolio;
NSString *strSoapMsg;
UIAlertView *alertView;
In your .m file use the following code:
-(void)callURL
{
//Your logic to call URL.
conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];
if (conn)
{
webPortFolio = [[NSMutableData data] retain];
}
}
And to handle the response you can use following functions :
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[webPortFolio setLength:0];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[webPortFolio appendData:data];
}
-(void) connection:(NSURLConnection *) connection didFailWithError:(NSError *) error
{
NSLog(#"error...................%#",[error description]);
[webPortFolio release];
[connection release];
}
-(void) connectionDidFinishLoading:(NSURLConnection *) connection
{
//Check the request and returns the response.
NSLog(#"DONE. Received Bytes: %d", [webPortFolio length]);
theXMLPortFolio = [[NSString alloc]
initWithBytes: [webPortFolio mutableBytes]
length:[webPortFolio length]
encoding:NSUTF8StringEncoding];
//---shows the XML---
NSLog(#"shows the XML %#",theXMLPortFolio);
[theXMLPortFolio release];
if(xmlParserPortFolio)
{
[xmlParserPortFolio release];
}
xmlParserPortFolio = [[NSXMLParser alloc] initWithData: webPortFolio];
[xmlParserPortFolio setDelegate: self];
[xmlParserPortFolio setShouldResolveExternalEntities:YES];
[xmlParserPortFolio parse];
[webPortFolio release];
[connection release];
}
//---when the start of an element is found---
-(void) parser:(NSXMLParser *) parser
didStartElement:(NSString *) elementName
namespaceURI:(NSString *) namespaceURI
qualifiedName:(NSString *) qName
attributes:(NSDictionary *) attributeDict
{
if( [elementName isEqualToString:#"your_tag_name"])
{
if (!soapResultsPortFolio)
{
soapResultsPortFolio = [[NSMutableString alloc] init];
}
elementFoundPortFolio = TRUE;
NSLog(#"Registration...%#",soapResultsPortFolio);
}
else if([elementName isEqualToString:#"your_tag_name"])
{
elementFoundPortFolio = TRUE;
}
else if([elementName isEqualToString:#"your_tag_name"])
{
elementFoundPortFolio = TRUE;
}
else if([elementName isEqualToString:#"your_tag_name"])
{
elementFoundPortFolio = TRUE;
}
}
-(void)parser:(NSXMLParser *) parser foundCharacters:(NSString *)string
{
if (elementFoundPortFolio)
{
[soapResultsPortFolio appendString: string];
}
}
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
NSLog(#"Parser error %# ",[parseError description]);
}
//---when the end of element is found---
-(void)parser:(NSXMLParser *)parser
didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:#"your_tag_name"])
{
NSLog(#"display the soap results%#",soapResultsPortFolio);
}
else if([elementName isEqualToString:#"your_tag_name"])
{
//Perform required action
}
else if([elementName isEqualToString:#"your_tag_name"])
{
//Perform required action
}
else if([elementName isEqualToString:#"your_tag_name"])
{
//Perform required action
}
[soapResultsPortFolio setString:#""];
elementFoundPortFolio = FALSE;
}

Having trouble understanding NSXMLParser

Im having trouble understanding NSXMLParser. I have tried some external XML Parsers but i have had no luck. What i am trying to do is parse the GDATA Youtube API xml which retrieves the xml for videos. This is working fine i have the xml but its difficult reiterating through the elements. I just need an example that can retrieve the elements such as (media:thumbnail url="" )(/media:thumbnail)
How to i get the url value from the element media:thumbnail
The url i am requesting is https://gdata.youtube.com/feeds/api/videos?q=football+-soccer&orderby=published&start-index=11&max-results=10&v=2
This is how you can use NSXMLParser :
In your .h file declare :
NSMutableData *webPortFolio;
NSMutableString *soapResultsPortFolio;
NSURLConnection *conn;
//---xml parsing---
NSXMLParser *xmlParserPortFolio;
BOOL elementFoundPortFolio;
NSMutableURLRequest *req;
NSString *theXMLPortFolio;
NSString *strSoapMsg;
UIAlertView *alertView;
In your .m file use the following code:
-(void)callURL
{
//Your logic to call URL.
conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];
if (conn)
{
webPortFolio = [[NSMutableData data] retain];
}
}
And to handle the response you can use following functions :
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[webPortFolio setLength:0];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[webPortFolio appendData:data];
}
-(void) connection:(NSURLConnection *) connection didFailWithError:(NSError *) error
{
NSLog(#"error...................%#",[error description]);
[webPortFolio release];
[connection release];
}
-(void) connectionDidFinishLoading:(NSURLConnection *) connection
{
//Check the request and returns the response.
NSLog(#"DONE. Received Bytes: %d", [webPortFolio length]);
theXMLPortFolio = [[NSString alloc]
initWithBytes: [webPortFolio mutableBytes]
length:[webPortFolio length]
encoding:NSUTF8StringEncoding];
//---shows the XML---
NSLog(#"shows the XML %#",theXMLPortFolio);
[theXMLPortFolio release];
if(xmlParserPortFolio)
{
[xmlParserPortFolio release];
}
xmlParserPortFolio = [[NSXMLParser alloc] initWithData: webPortFolio];
[xmlParserPortFolio setDelegate: self];
[xmlParserPortFolio setShouldResolveExternalEntities:YES];
[xmlParserPortFolio parse];
[webPortFolio release];
[connection release];
}
//---when the start of an element is found---
-(void) parser:(NSXMLParser *) parser
didStartElement:(NSString *) elementName
namespaceURI:(NSString *) namespaceURI
qualifiedName:(NSString *) qName
attributes:(NSDictionary *) attributeDict
{
if( [elementName isEqualToString:#"GetPortfolioListResult"])
{
if (!soapResultsPortFolio)
{
soapResultsPortFolio = [[NSMutableString alloc] init];
}
elementFoundPortFolio = TRUE;
NSLog(#"Registration...%#",soapResultsPortFolio);
}
else if([elementName isEqualToString:#"your_tag_name"])
{
elementFoundPortFolio = TRUE;
}
else if([elementName isEqualToString:#"your_tag_name"])
{
elementFoundPortFolio = TRUE;
}
else if([elementName isEqualToString:#"your_tag_name"])
{
elementFoundPortFolio = TRUE;
}
}
-(void)parser:(NSXMLParser *) parser foundCharacters:(NSString *)string
{
if (elementFoundPortFolio)
{
[soapResultsPortFolio appendString: string];
}
}
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
NSLog(#"Parser error %# ",[parseError description]);
}
//---when the end of element is found---
-(void)parser:(NSXMLParser *)parser
didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:#"GetPortfolioListResult"])
{
NSLog(#"display the soap results%#",soapResultsPortFolio);
}
else if([elementName isEqualToString:#"your_tag_name"])
{
//Perform required action
}
else if([elementName isEqualToString:#"your_tag_name"])
{
//Perform required action
}
else if([elementName isEqualToString:#"your_tag_name"])
{
//Perform required action
}
[soapResultsPortFolio setString:#""];
elementFoundPortFolio = FALSE;
}
EDIT :
if ([elementName isEqualToString:#"media:thumbnail"])
{
//Save your URL in an Array
}

iPhone: How to access multiple XMLs in the same view

I am trying to read data from two different XML's to populate fields of my View in iPhone.
Is there any way to read multiple XML's in the same view? I can read and parse a single XML.
Thanks
//Using the NSXML Parser
-(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(#"Connection Error");
[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(#"XML value %#",theXML);
[theXML release];
if (xmlParser) {
[xmlParser release];
}
xmlParser = [[NSXMLParser alloc]initWithData:webData];
[xmlParser setDelegate:self];
[xmlParser setShouldResolveExternalEntities:YES];
[xmlParser parse];
[connection release];
[webData release];
}
- (void)parserDidStartDocument:(NSXMLParser *)parser{
NSLog(#"found file and started parsing");
//colorTypes = [[NSMutableArray alloc]init];
propertyCategories = [[NSMutableArray alloc]init];
}
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString
*)elementName namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName attributes:(NSDictionary
*)attributeDict{
if ([elementName isEqualToString:#"GetCommonCodeByCatgResult"]) {
}
if ([elementName isEqualToString:#"SvcCommonCode"]) {
aCategory =[[Category alloc]init];
aCategory.CMCodeDesc = [attributeDict objectForKey:#"CMCodeDesc"];
}
}
-(void)parser: (NSXMLParser *)parser foundCharacters:(NSString *)string{
if (!currentElementValue)
currentElementValue =[[NSMutableString alloc]initWithString:string];
else
[currentElementValue appendString:string];
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString
*)elementName namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:#"GetCommonCodeByCatgResult"]) {
[itemCategoryList reloadAllComponents];
//[colorList reloadAllComponents];
return;
}
if ([elementName isEqualToString:#"SvcCommonCode"]) {
[propertyCategories addObject:aCategory.CMCodeDesc];
//[colorTypes addObject: aCategory.CMCodeDesc];
[aCategory release];
aCategory =nil;
}
else
[aCategory setValue:currentElementValue forKey:elementName];
[currentElementValue release];
currentElementValue = nil;
}
Use a Boolean, name it isParsingNextString to parse a different string and elements.
//in viewDidLoad
isParsingNextString = NO;
//put this inside your begin parsing method
if (isParsingNextString == NO) {
//parse 1st string URL
}
if (isParsingNextString == YES) {
//parse 2nd string URL
}
//when your document finishes set the bool to yes
//now restart your parser inside an if statement so you dont have a parsing loop
if(isParsingNextString == NO) {
isParsingNextString = YES;
[self parseXML];
}

RSS Reader error

I am currently doing an application which make use of the RSS Feed from http://www.learnerstogether.net/. However i keep getting the error unable to download the XML data from the website. Can someone tell me what is wrong.
#implementation Parser
#synthesize items, responseData;
#synthesize currentTitle;
#synthesize currentDate;
#synthesize currentSummary;
#synthesize currentLink;
#synthesize currentPodcastLink;
- (void)parseRssFeed:(NSString *)url withDelegate:(id)aDelegate {
[self setDelegate:aDelegate];
responseData = [[NSMutableData data] retain];
NSURL *baseURL = [[NSURL URLWithString:url] retain];
NSURLRequest *request = [NSURLRequest requestWithURL:baseURL];
[[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSString * errorString = [NSString stringWithFormat:#"Unable to download xml data (Error code %i )", [error code]];
UIAlertView * errorAlert = [[UIAlertView alloc] initWithTitle:#"Error loading content" message:errorString delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorAlert show];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
self.items = [[NSMutableArray alloc] init];
NSXMLParser *rssParser = [[NSXMLParser alloc] initWithData:responseData];
[rssParser setDelegate:self];
[rssParser parse];
}
#pragma mark rssParser methods
- (void)parserDidStartDocument:(NSXMLParser *)parser {
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
currentElement = [elementName copy];
if ([elementName isEqualToString:#"item"]) {
item = [[NSMutableDictionary alloc] init];
self.currentTitle = [[NSMutableString alloc] init];
self.currentDate = [[NSMutableString alloc] init];
self.currentSummary = [[NSMutableString alloc] init];
self.currentLink = [[NSMutableString alloc] init];
self.currentPodcastLink = [[NSMutableString alloc] init];
}
// podcast url is an attribute of the element enclosure
if ([currentElement isEqualToString:#"enclosure"]) {
[currentPodcastLink appendString:[attributeDict objectForKey:#"url"]];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:#"item"]) {
[item setObject:self.currentTitle forKey:#"title"];
[item setObject:self.currentLink forKey:#"link"];
[item setObject:self.currentSummary forKey:#"summary"];
[item setObject:self.currentPodcastLink forKey:#"podcastLink"];
// Parse date here
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setDateFormat:#"E, d LLL yyyy HH:mm:ss Z"]; // Thu, 18 Jun 2010 04:48:09 -0700
NSDate *date = [dateFormatter dateFromString:self.currentDate];
[item setObject:date forKey:#"date"];
[items addObject:[item copy]];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if ([currentElement isEqualToString:#"title"]) {
[self.currentTitle appendString:string];
} else if ([currentElement isEqualToString:#"link"]) {
[self.currentLink appendString:string];
} else if ([currentElement isEqualToString:#"description"]) {
[self.currentSummary appendString:string];
} else if ([currentElement isEqualToString:#"pubDate"]) {
[self.currentDate appendString:string];
NSCharacterSet* charsToTrim = [NSCharacterSet characterSetWithCharactersInString:#" \n"];
[self.currentDate setString: [self.currentDate stringByTrimmingCharactersInSet: charsToTrim]];
}
}
- (void)parserDidEndDocument:(NSXMLParser *)parser {
if ([_delegate respondsToSelector:#selector(receivedItems:)])
[_delegate receivedItems:items];
else
{
[NSException raise:NSInternalInconsistencyException
format:#"Delegate doesn't respond to receivedItems:"];
}
}
#pragma mark Delegate methods
- (id)delegate {
return _delegate;
}
- (void)setDelegate:(id)new_delegate {
_delegate = new_delegate;
}
- (void)dealloc {
[items release];
[responseData release];
[super dealloc];
}
#end
Your error has absolutely nothing to do with the RSS parsing aspect of this. What's more, you haven't even pasted in the full error. You should log the error object itself in your implementation of -connection:didFailWithError:. That should give you a human-readable description of what went wrong.

NSMutableArray populated but data lost somehow

I start process of getting data from viewDidLoad and populate NSMutableArray with that data. But when I want to populate UIPicker I cant because there is no more data in that array. How did I lost that??? Please help :(
#synthesize activityIndicator;
#synthesize pckCountries;
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
countriesList = [[NSMutableArray alloc] initWithCapacity:20];
[self getCountriesList];
NSLog(#"%#", [countriesList count]);
[super viewDidLoad];
}
- (void)dealloc {
[activityIndicator release];
[xmlParser release];
//[soapResults release];
[super dealloc];
}
- (void) getCountriesList{
NSString *soapMsg =
[NSString stringWithFormat:
#"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
"<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/\">"
"<soap:Body>"
"<getCountries xmlns=\"http://www.smsbug.com/api/\" />"
"</soap:Body>"
"</soap:Envelope>"
];
NSURL *url = [NSURL URLWithString:
#"http://www.smsbug.com/api/webservice.asmx"];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
NSString *msgLength = [NSString stringWithFormat:#"%d", [soapMsg length]];
[req addValue:#"text/xml; charset=utf-8"
forHTTPHeaderField:#"Content-Type"];
[req addValue:#"http://www.smsbug.com/api/getCountries"
forHTTPHeaderField:#"SOAPAction"];
[req addValue:msgLength forHTTPHeaderField:#"Content-Length"];
[req setHTTPMethod:#"POST"];
[req setHTTPBody: [soapMsg dataUsingEncoding:NSUTF8StringEncoding]];
conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];
if (conn) {
webData = [[NSMutableData data] retain];
}
}
-(void) connection:(NSURLConnection *) connection
didReceiveResponse:(NSURLResponse *) response {
[webData setLength: 0];
}
-(void) connection:(NSURLConnection *) connection
didReceiveData:(NSData *) data {
[webData appendData:data];
NSLog(#"%#", webData);
}
-(void) connection:(NSURLConnection *) connection
didFailWithError:(NSError *) error {
[webData release];
[connection release];
}
-(void) connectionDidFinishLoading:(NSURLConnection *) connection {
NSLog(#"DONE READING WEATHER WEB SERVICE. Received Bytes: %d", [webData length]);
NSString *theXML = [[NSString alloc]
initWithBytes: [webData mutableBytes]
length:[webData length]
encoding:NSUTF8StringEncoding];
//---shows the XML to test---
NSLog(theXML);
[theXML release];
// stop activity indicator animation
[activityIndicator stopAnimating];
//-----------------------------------------------------------------
// start parsing received XML message
//-----------------------------------------------------------------
if (xmlParser)
{
[xmlParser release];
}
xmlParser = [[NSXMLParser alloc] initWithData: webData];
[xmlParser setDelegate:self];
[xmlParser setShouldResolveExternalEntities:YES];
[xmlParser parse];
// clear memory
[connection release];
[webData release];
}
-(void) parser:(NSXMLParser *) parser
didStartElement:(NSString *) elementName
namespaceURI:(NSString *) namespaceURI
qualifiedName:(NSString *) qName
attributes:(NSDictionary *) attributeDict {
//NSLog(elementName);
if ([elementName isEqualToString:#"Country_Name"])
{
countryFound = YES;
}
}
-(void)parser:(NSXMLParser *) parser foundCharacters:(NSString *)string
{
if([string isEqualToString:#"Data Not Found"])
{
errorOccured = YES;
}
else if(countryFound == YES)
{
//NSLog(string);
[countriesList addObject:string];
}
else
{
[soapResults appendString: string];
}
}
-(void)parser:(NSXMLParser *)parser
didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
{
if(errorOccured == YES)
{
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"No Data!"
message:#"Sorry"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
[soapResults setString:#""];
errorOccured = FALSE;
}
else
{
if ([elementName isEqualToString:#"Country_Name"])
{
countryFound = FALSE;
}
}
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
return countriesList.count;
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{
return [countriesList objectAtIndex:row];
}
[super viewDidLoad] should be the first invocation in a viewDidLoad method.
There's a leak - you should invoke [countriesList release] in a dealloc method.
NSURLRequest is asynchronous. As well as NSXMLParser. So all picker delegate methods will be called before downloading/parsing is finished. Thus, in all delegate methods you should check if countriesList is equal to nil.
When parsing is finished (implement parserDidEndDocument: method to receive this message) you should explicitly call [picker reloadAllComponents].