NSOperation subclass not calling delegate methods and NSOperationQueue not waiting until finished - iphone

I use this piece of code to create some NSOperations and add them to a queue:
HUD = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES];
//HUD.labelText = #"Downloading..";
//HUD.dimBackground = YES;
/* Operation Queue init */
NSOperationQueue *queue = [NSOperationQueue new];
// Spawn request operations & add them to queue
SoapRequestOperation *operation = [[SoapRequestOperation alloc] initWithRequest:#"<?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> <Categories xmlns=\"http://tempuri.org/\"> <UID>string</UID> <Username>string</Username> <Password>string</Password> </Categories> </soap:Body> </soap:Envelope>" andValue:#"Categories"];
[queue addOperation:operation];
operation = [[SoapRequestOperation alloc] initWithRequest:#"<?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> <Currencies xmlns=\"http://tempuri.org/\"> <UID>string</UID> <Username>string</Username> <Password>string</Password> </Currencies> </soap:Body> </soap:Envelope>" andValue:#"Currencies"];
[queue addOperation:operation];
operation = [[SoapRequestOperation alloc] initWithRequest:#"<?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> <Nominals xmlns=\"http://tempuri.org/\"> <UID>string</UID> <Username>string</Username> <Password>string</Password> </Nominals> </soap:Body> </soap:Envelope>" andValue:#"Nominals"];
[queue addOperation:operation];
operation = [[SoapRequestOperation alloc] initWithRequest:#"<?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> <Projects xmlns=\"http://tempuri.org/\"> <UID>string</UID> <Username>string</Username> <Password>string</Password> </Projects> </soap:Body> </soap:Envelope>" andValue:#"Projects"];
[queue addOperation:operation];
operation = [[SoapRequestOperation alloc] initWithRequest:#"<?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> <Register xmlns=\"http://tempuri.org/\"> <UID>string</UID> <Username>string</Username> <Password>string</Password> <OrganisationCode>string</OrganisationCode> </Register> </soap:Body> </soap:Envelope>" andValue:#"Register"];
[queue addOperation:operation];
[queue waitUntilAllOperationsAreFinished];
[self reloadTableData];
HUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"37x-Checkmark.png"]];
HUD.mode = MBProgressHUDModeCustomView;
[HUD hide:YES afterDelay:2];
This is the .m file for my NSOperation subclass:
#import "SoapRequestOperation.h"
#import "Currency.h"
#import "Category.h"
#import "Project.h"
#import "Constants.h"
#implementation SoapRequestOperation
#synthesize request, value;
-(id) initWithRequest:(NSString *)l_Request andValue:(NSString *)l_Value{
if (self = [super init]) {
/* do most of initialization */
self.request = l_Request;
self.value = l_Value;
xmlBlock = 0;
appDelegate = [[UIApplication sharedApplication] delegate];
}
return(self);
}
- (void) main {
if ([value isEqualToString:#"Category"]){
xmlBlock = CATEGORY;
}
else if ([value isEqualToString:#"Currency"]){
xmlBlock = CURRENCY;
}
else if ([value isEqualToString:#"Nominal"]){
xmlBlock = NOMINAL;
}
else if ([value isEqualToString:#"Project"]){
xmlBlock = PROJECT;
}
else {
xmlBlock = REGISTER;
}
NSString *soapMsg = request;
//---print it to the Debugger Console for verification---
NSLog(#"%#", soapMsg);
NSURL *url = [NSURL URLWithString:
#"http://www.$^$%£%#%^£.co.uk/$$^$^£$^£.asmx"];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
//---set the headers---
NSString *msgLength = [NSString stringWithFormat:#"%d",
[soapMsg length]];
[req addValue:#"text/xml; charset=utf-8"
forHTTPHeaderField:#"Content-Type"];
[req addValue:[NSString stringWithFormat:#"http://tempuri.org/%#", value]
forHTTPHeaderField:#"SOAPAction"];
[req addValue:msgLength forHTTPHeaderField:#"Content-Length"];
//---set the HTTP method and body---
[req setHTTPMethod:#"POST"];
[req setHTTPBody: [soapMsg dataUsingEncoding:NSUTF8StringEncoding]];
//[activityIndicator startAnimating];
conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];
if (conn) {
webData = [NSMutableData data];
}
}
-(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 {
}
-(void) connectionDidFinishLoading:(NSURLConnection *) connection {
NSLog(#"DONE. Received Bytes: %d", [webData length]);
NSString *theXML = [[NSString alloc]
initWithBytes: [webData mutableBytes]
length:[webData length]
encoding:NSUTF8StringEncoding];
//---shows the XML---
NSLog(#"%#", theXML);
xmlParser = [[NSXMLParser alloc] initWithData: webData];
[xmlParser setDelegate: self];
[xmlParser setShouldResolveExternalEntities:YES];
[xmlParser parse];
}
//---when the start of an element is found---
-(void) parser:(NSXMLParser *) parser
didStartElement:(NSString *) elementName
namespaceURI:(NSString *) namespaceURI
qualifiedName:(NSString *) qName
attributes:(NSDictionary *) attributeDict {
currentElement = [elementName copy];
//Category
if( [currentElement isEqualToString:#"Item"])
{
category = [[NSMutableDictionary alloc] init];
categoryName = [[NSMutableString alloc] init];
}
//Currency
if ([currentElement isEqualToString: #"Currency"]) {
currency = [[NSMutableDictionary alloc] init];
countryName = [[NSMutableString alloc] init];
currencyName = [[NSMutableString alloc] init];
currencyUnit = [[NSMutableString alloc] init];
shortName = [[NSMutableString alloc] init];
}
//Nominal
if( [currentElement isEqualToString:#"Nominal"])
{
nominal = [[NSMutableDictionary alloc] init];
name = [[NSMutableString alloc] init];
description = [[NSMutableString alloc] init];
paid = [[NSMutableString alloc] init];
}
//Project
if( [currentElement isEqualToString:#"Project"])
{
project = [[NSMutableDictionary alloc] init];
projectName = [[NSMutableString alloc] init];
projectDescription = [[NSMutableString alloc] init];
}
//Register
if( [currentElement isEqualToString:#"RegisterResult"])
{
elementFound = YES;
}
}
-(void)parser:(NSXMLParser *) parser foundCharacters:(NSString *)string
{
//Category
if (xmlBlock == CATEGORY){
if ([currentElement isEqualToString: #"Item"]){
[categoryName appendString:string];
}
}
//Currency
if (xmlBlock == CURRENCY){
if ([currentElement isEqualToString: #"CountryName"]){
[countryName appendString:string];
}
else if ([currentElement isEqualToString: #"CurrencyName"]){
[currencyName appendString:string];
}
else if ([currentElement isEqualToString: #"Unit"]){
[currencyUnit appendString:string];
}
else if ([currentElement isEqualToString: #"ShortName"]){
[shortName appendString:string];
}
}
//Nominal
if ([currentElement isEqualToString: #"Name"] && xmlBlock == NOMINAL){
[name appendString:string];
}
else if ([currentElement isEqualToString: #"Description"] && xmlBlock == NOMINAL){
[description appendString:string];
}
else if ([currentElement isEqualToString: #"Paid"]){
[paid appendString:string];
}
//Project
if (xmlBlock == PROJECT) {
if ([currentElement isEqualToString: #"Name"]){
[projectName appendString:string];
}
else if ([currentElement isEqualToString: #"Description"]){
[projectDescription appendString:string];
}
}
//Register
if (xmlBlock == REGISTER && elementFound){
registerVal = string;
}
}
//---when the end of element is found---
-(void)parser:(NSXMLParser *)parser
didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:#"Item"])
{
// save values to an item, then store that item into the array...
[category setObject:categoryName forKey:#"categoryName"];
[categories addObject:[category copy]];
Category *c = [[Category alloc] init];
c.categoryName = categoryName;
c.totalValue = #"0.00";
[appDelegate.categories addObject:c];
NSLog(#"%d", [appDelegate.categories count]);
}
//Currency
if ([elementName isEqualToString: #"Currency"]) {
// save values to an item, then store that item into the array...
[currency setObject:countryName forKey:#"countryName"];
[currency setObject:currencyName forKey:#"currencyName"];
[currency setObject:currencyUnit forKey:#"unit"];
[currency setObject:shortName forKey:#"shortName"];
[currencies addObject:[currency copy]];
Currency *c = [[Currency alloc] init];
c.totalValue = #"0.00";
c.countryName = countryName;
c.currencyName = currencyName;
double myDouble = [currencyUnit doubleValue];
c.unit = myDouble;
c.shortName = shortName;
[appDelegate.currencies addObject:c];
NSLog(#"%d", [appDelegate.currencies count]);
}
//Nominal
if ([elementName isEqualToString:#"Nominal"])
{
// save values to an item, then store that item into the array...
[nominal setObject:name forKey:#"name"];
[nominal setObject:description forKey:#"description"];
[nominal setObject:paid forKey:#"paid"];
[nominals addObject:[nominal copy]];
NSLog(#"%d", [nominals count]);
}
if ([elementName isEqualToString:#"Project"])
{
// save values to an item, then store that item into the array...
[project setObject:projectName forKey:#"projectName"];
[project setObject:projectDescription forKey:#"projectDescription"];
[projects addObject:[project copy]];
Project *p = [NSEntityDescription
insertNewObjectForEntityForName:#"Project"
inManagedObjectContext:appDelegate.managedObjectContext];
[p setValue:projectName forKey:#"name"];
[p setValue:#"0.00" forKey:#"totalValue"];
NSError *error;
if (![appDelegate.managedObjectContext save:&error]) {
NSLog(#"Whoops, couldn't save: %#", [error localizedDescription]);
}
[appDelegate.projects addObject:p];
NSLog(#"%d", [appDelegate.currencies count]);
}
if ([elementName isEqualToString:#"RegisterResult"])
{
if ([registerVal isEqualToString:#"true"]){
boolRegister = YES;
}
else {
boolRegister = NO;
}
NSLog(#"BOOL = %#", (boolRegister ? #"YES" : #"NO"));
elementFound = FALSE;
}
}
Unfortunately, the NSURLConnection and NSXMLParser delegate methods are not being called (everything is as it should be in the header file). And I'm not sure I fully understand the line:
[queue waitUntilAllOperationsAreFinished];
Should this not cause the calling thread to wait until all the operations are completed? I have a feeling this line isn't working due to the faults with the NSOperation subclass itself?
Can anyone help me out here?
Thanks a lot,
Jack

The issue is how you have setup your operation. It is setup as a non-concurrent operation so it is executing the main method in a separate thread then finishing up. By the time the delegates are called, the thread is gone. Poof. Your issue is you are not keeping the thread around. See here: How do I do an Asychronous NSURLConnection inside an NSOperation?

Joel is correct in the start method you should call the main method to be start on the main thread, or you need to keep alive the thread in wich the method id called.

Related

Create an array of integers from an array of objects (id) and send to a web service

I'm creating an app iOS that requires the connection to a web service such as "http://xxx.xxx.xx.xxx/WebSiteServices.svc?wsdl".
The app allows to make a quote for a trip with luggage, after selecting some fields:
Country of origin (list of countries of origin);
Country of destination (list of countries of destination);
5 identification fields for 5 id of luggage, each allowing to select the number of bags with different id.
To communicate with the web service I made a SOAP call as explained in the link: "iPhone interaction with ASP.NET WebService."
I succeeded to receive lists of nations and luggage, now I cannot send the selected data to the web service to invoke the "calcolaImporto" (Calculate Amount) method. I have to send in the SOAP message:
idPaesePrelievo: Id of the country of origin (an Integer: OK, I succeded);
idPaeseDest: Id of the destination country (an Integer: OK, I succeded);
idProdotti: List of integers that identifies the id of the selected storage (PROBLEM: I cannot send the array);
qtaProdotti: List of integers that identifies the amount of luggage id selected for each of the first list (PROBLEM: I cannot send the array).
The two lists are not connected to each other, but I cannot send to the web service these two arrays.
The arrays in the web service are composed by two lists of integers, even if the two array of Xcode are composed by two lists of object id (I also tried doing the cast from id to int, but nothing).
The method is accessed, but the result is '0' because it is not checked any luggage: how can I do?
PLEASE help me, thank you!
Below I have posted the code of “ViewController.m”:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize amount, idPaeseDest, idPaesePrelievo, idProdotti, qtaProdotti;
/* amount (TEXTFIELD), idPaeseDest (INT), idPaesePrelievo (INT), idProdotti (NSMUTABLEARRAY), qtaProdotti (NSMUTABLEARRAY) */
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)calcolaImporto:(id)sender {
// Create the SOAP message
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>"
"<CalcolaImporto xmlns=\"http://tempuri.org/\">"
"<idPaesePrelievo>%d</idPaesePrelievo>"
"<idPaeseDest>%d</idPaeseDest>"
"<idProdotti>%#</idProdotti>"
"<qtaProdotti>%#</qtaProdotti>"
"</CalcolaImporto>"
"</soap:Body>"
"</soap:Envelope>", idPaesePrelievo, idPaeseDest, idProdotti, qtaProdotti];
// Create the URL
NSURL *url = [NSURL URLWithString: #"http://xxx.xxx.xx.xxx/WebSiteServices.svc?wsdl"];
// Create the request
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://tempuri.org/IBagExpressServices/CalcolaImporto" 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];
}
-(void) connection:(NSURLConnection *) connection didFailWithError:(NSError *) error {
UIAlertView *errore = [[UIAlertView alloc] initWithTitle:#"ERROR" message:#"Connection problem" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errore show];
[errore release];
[webData release];
[connection release];
}
-(void) connectionDidFinishLoading:(NSURLConnection *) connection {
NSLog(#"Ok. Byte: \n %d", [webData length]);
NSString *theXML = [[NSString alloc] initWithBytes: [webData mutableBytes] length:[webData length] encoding:NSUTF8StringEncoding];
NSLog(#"theXML: \n %#", 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) parser:(NSXMLParser *) parser didStartElement:(NSString *) elementName namespaceURI:(NSString *) namespaceURI qualifiedName:(NSString *) qName attributes:(NSDictionary *) attributeDict {
if ([elementName isEqualToString:#"CalcolaImportoResponse"])
soapResults = [[NSMutableString alloc] init];
elementFound = YES;
}
-(void)parser:(NSXMLParser *) parser foundCharacters:(NSString *)string {
if (elementFound)
[soapResults appendString:string];
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:#"CalcolaImportoResult"])
amount.text=soapResults;
elementFound = FALSE;
}
- (void)dealloc {
[amount release];
[soapResults release];
[super dealloc];
}
#end
Can't you create a NSString with the list of integers and separate them by , and send that instead?
NSMutableString *mutableList = [[NSMutableString alloc ]initWithString:#"<q14:ArrayOfint>"];
//I'll say like this because i don't know if you added them as NSNumber or NSString
for(int i = 0 ;i < idProdotti.count;i++)
{
NSInteger value = [[idProdotti objectAtIndex:i]integerValue];
[mutableList appendFormat:#"<arr:int>%d</arr:int>",value];
}
[mutableList appendFormat:#"</q14:ArrayOfint>"];
and send mutableList then release it;
//second one for qtaProdotti
NSMutableString *mutableList1 = [[NSMutableString alloc ]initWithString:#"<q15:ArrayOfint>"];
//I'll say like this because i don't know if you added them as NSNumber or NSString
for(int i = 0 ;i < qtaProdotti.count;i++)
{
NSInteger value = [[qtaProdotti objectAtIndex:i]integerValue];
[mutableList1 appendFormat:#"<arr:int>%d</arr:int>",value];
}
[mutableList1 appendFormat:#"</q15:ArrayOfint>"];
and send mutableList1 then release it;
I solved in this way:
I used "SoapUI", a graphical interface to interact with the web services, and I rewrote the SOAP message;
I used two lists similar to those that showed me "Soryngod".
Here's the correct code:
NSMutableString *idLista = [[NSMutableString alloc] init];
for(int i=0; i<idProdotti.count; i++) {
NSInteger value = [[idProdotti objectAtIndex:i] integerValue];
[idLista appendFormat:#"<arr:int>%d</arr:int>",value];
}
NSMutableString *qtaLista = [[NSMutableString alloc] init];
for(int i=0; i<qtaProdotti.count; i++) {
NSInteger value = [[qtaProdotti objectAtIndex:i] integerValue];
[qtaLista appendFormat:#"<arr:int>%d</arr:int>",value];
}
NSString *soapMsg = [NSString stringWithFormat: #"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
"<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/\" xmlns:tem="http://tempuri.org/\" xmlns:arr="http://schemas.microsoft.com/2003/10/Serialization/Arrays\">"
"<soapenv:Body>"
"<tem:CalcolaImporto>"
"<tem:idPaesePrelievo>%d</tem:idPaesePrelievo>"
"<tem:idPaeseDest>%d</tem:idPaeseDest>"
"<tem:idProdotti>%#</tem:idProdotti>"
"<tem:qtaProdotti>%#</tem:qtaProdotti>"
"</tem:CalcolaImporto>"
"</soapenv:Body>"
"</soapenv:Envelope>", idPaesePrelievo, idPaeseDest, idLista, qtaLista];
[...]

Using GDataXML to Parse Included XML File

This XML will be included in the app:
<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Directory</title>
<description>Directory of Members</description>
<language>en</language>
<item>
<LastName></LastName>
<FirstName></FirstName>
<Address></Address>
<Phone></Phone>
<Email></Email>
</item>
<item>
<LastName></LastName>
<FirstName></FirstName>
<Address></Address>
<Phone></Phone>
<Email></Email>
</item>
</channel>
</rss>
I would like to be able to parse the XML and store into an RSSEntry Class that I have done before with other XMLs. The issue is that the only other XMLs I have worked with have been located online, and I use ASIHttpRequest Classes as part of the method, and am unsure how to go about changing the code to make it fit. I currently use this code:
- (void)viewDidLoad {
[super viewDidLoad];
self.allEntries = [NSMutableArray array];
self.queue = [[[NSOperationQueue alloc] init] autorelease];
self.feeds = [NSArray arrayWithObjects:#"http://316apps.com/LakesideNews/feed/",
nil];
NSLog(#"%#", self.feeds);
[self refresh];
}
- (void)refresh {
for (NSString *feed in _feeds) {
NSURL *url = [NSURL URLWithString:feed];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[_queue addOperation:request];
}
}
- (void)parseRss:(GDataXMLElement *)rootElement entries:(NSMutableArray *)entries {
NSArray *channels = [rootElement elementsForName:#"channel"];
for (GDataXMLElement *channel in channels) {
NSString *blogTitle = [channel valueForChild:#"title"];
NSArray *items = [channel elementsForName:#"item"];
for (GDataXMLElement *item in items) {
NSString *articleTitle = [item valueForChild:#"title"];
NSString *articleUrl = [item valueForChild:#"guid"];
NSString *articleDateString = [item valueForChild:#"pubDate"];
NSDate *articleDate = [NSDate dateFromInternetDateTimeString:articleDateString formatHint:DateFormatHintRFC822];
NSString *articleImage = [item valueForChild:#"content:encoded"];
RSSEntry *entry = [[[RSSEntry alloc] initWithBlogTitle:blogTitle
articleTitle:articleTitle
articleUrl:articleUrl
articleDate:articleDate
articleImage:articleImage] autorelease];
[entries addObject:entry];
}
}
}
- (void)parseFeed:(GDataXMLElement *)rootElement entries:(NSMutableArray *)entries {
if ([rootElement.name compare:#"rss"] == NSOrderedSame) {
[self parseRss:rootElement entries:entries];
} else if ([rootElement.name compare:#"feed"] == NSOrderedSame) {
[self parseAtom:rootElement entries:entries];
} else {
NSLog(#"Unsupported root element: %#", rootElement.name);
}
}
- (void)requestFinished:(ASIHTTPRequest *)request {
[_queue addOperationWithBlock:^{
NSError *error;
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:[request responseData]
options:0 error:&error];
if (doc == nil) {
NSLog(#"Failed to parse %#", request.url);
} else {
NSMutableArray *entries = [NSMutableArray array];
[self parseFeed:doc.rootElement entries:entries];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
for (RSSEntry *entry in entries) {
int insertIdx = [_allEntries indexForInsertingObject:entry sortedUsingBlock:^(id a, id b) {
RSSEntry *entry1 = (RSSEntry *) a;
RSSEntry *entry2 = (RSSEntry *) b;
return [entry1.articleDate compare:entry2.articleDate];
}];
[_allEntries insertObject:entry atIndex:insertIdx];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:insertIdx inSection:0]]
withRowAnimation:UITableViewRowAnimationRight];
}
}];
}
}];
}
- (void)requestFailed:(ASIHTTPRequest *)request {
NSError *error = [request error];
NSLog(#"Error: %#", error);
[self refresh];
}
I know to change all the areas for Title to things like Family name, etc., I just don't know how to go about getting the GDataXML to begin parsing the nested XML.
Ray Wenderlich has a fantastic tutorial covering exactly what you are doing. I would start there. Here's the link.

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].

Date comparison Iphone

i have a range of weekly dates like example
1-5-2010 to 7-5-2010
i want the only records which are between two dates how can i compare dates?
and how can i get current week dates.. from current dates...?
thnx in advance..
//alert handler
#import <Foundation/Foundation.h>
#interface AlertHandler : NSObject {
}
+(void)showAlertForProcess;
+(void)hideAlert;
#end
#import "AlertHandler.h"
#implementation AlertHandler
UIAlertView *av;
UIActivityIndicatorView *actInd;
+(void)showAlertForProcess{
if(av!=nil && [av retainCount]>0){ [av release]; av=nil; }
if(actInd!=nil && [actInd retainCount]>0){ [actInd removeFromSuperview];[actInd release]; actInd=nil; }
av=[[UIAlertView alloc] initWithTitle:#"Loading" message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:nil];
actInd=[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[actInd setFrame:CGRectMake(120, 50, 37, 37)];
[actInd startAnimating];
[av addSubview:actInd];
[av show];
}
+(void)hideAlert{
[av dismissWithClickedButtonIndex:0 animated:YES];
if(av!=nil && [av retainCount]>0){ [av release]; av=nil; }
if(actInd!=nil && [actInd retainCount]>0){ [actInd removeFromSuperview];[actInd release]; actInd=nil; }
}
#end
///Sample of webservice..
-(void)callWebServiceForSignUp{
[AlertHandler showAlertForProcess];
if([gender.text isEqualToString: #"Male"]){
gen=[NSString stringWithFormat:#"1"];
}
else{
gen=[NSString stringWithFormat:#"0"];
}
NSString *soapMsg = [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"
"<AddUser xmlns=\"http://tempuri.org/\">\n"
"<UserName>%#</UserName>\n"
"<UserEmail>%#</UserEmail>\n"
"<FirstName>%#</FirstName>\n"
"<LastName>%#</LastName>\n"
"<Gender>%#</Gender>\n"
"</AddUser>\n"
"</soap:Body>\n"
"</soap:Envelope>\n",username.text,email.text,firstname.text,lastname.text,gen];
NSURL *myURL=[NSURL URLWithString:[WebService getLoginURL]];
NSMutableURLRequest *connectionReq=[NSMutableURLRequest requestWithURL:myURL];
[connectionReq addValue:#"text/xml; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[connectionReq addValue:# "http://tempuri.org/AddUser" forHTTPHeaderField:#"SOAPAction"];
[connectionReq setHTTPBody: [soapMsg dataUsingEncoding:NSUTF8StringEncoding]];
[connectionReq addValue:[NSString stringWithFormat:#"%i",[soapMsg length]] forHTTPHeaderField:#"Content-Length"];
[connectionReq setHTTPMethod:#"POST"];
NSURLConnection *myConnection=[[NSURLConnection alloc] initWithRequest:connectionReq delegate:self];
if(myConnection){
myWebData=[[NSMutableData alloc] initWithLength:0];
}else{
UIAlertView *ConnectionNullAlert = [[UIAlertView alloc]initWithFrame:CGRectMake(10, 170, 300, 120)];
ConnectionNullAlert.message=#" can't able to connect to Server!";
ConnectionNullAlert.title=#"Message";
[ConnectionNullAlert addButtonWithTitle:#"OK"];
[ConnectionNullAlert show];
[ConnectionNullAlert release];
}
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
UIAlertView *ConnectionFailAlert = [[UIAlertView alloc]initWithFrame:CGRectMake(10, 170, 300, 120)];
ConnectionFailAlert.message=#" can't able to connect to Server!";
ConnectionFailAlert.title=#"Message";
[ConnectionFailAlert addButtonWithTitle:#"OK"];
[ConnectionFailAlert show];
[ConnectionFailAlert release];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
[myWebData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
[myWebData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
NSString *str=[[NSString alloc] initWithBytes:[myWebData bytes] length:[myWebData length] encoding:NSStringEncodingConversionAllowLossy];
NSLog(#"%#",str);
[str release];
if(myXMLParser!=nil && [myXMLParser retainCount]>0){ myXMLParser.delegate=nil; [myXMLParser release]; myXMLParser=nil; }
myXMLParser=[[NSXMLParser alloc] initWithData:myWebData];
myXMLParser.delegate=self;
[myXMLParser parse];
[myWebData release];
}
#pragma mark XMLParser methods
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict{
if([elementName isEqualToString:#"AddUserResult"]){
tempDic=[[NSMutableDictionary alloc] init];
}
}
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if(tmpStr!=nil && [tmpStr retainCount]>0){ [tmpStr release]; tmpStr=nil; }
tmpStr=[[NSString alloc] initWithString:string];
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if([elementName isEqualToString:#"AddUserResult"] ||
[elementName isEqualToString:#"User_Id"]){
[tempDic setValue:tmpStr forKey:elementName];
NSLog([tempDic description]);
}
}
-(void)parserDidEndDocument:(NSXMLParser *)parser{
[AlertHandler hideAlert];
NSString *errorDesc;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *DataPath = [documentsDirectory stringByAppendingPathComponent:#"Login.plist"];
NSDictionary *plistDict = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects: [tempDic valueForKey:#"User_Id"], nil] forKeys:[NSArray arrayWithObjects:#"userid", nil]];
NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:plistDict format:NSPropertyListXMLFormat_v1_0 errorDescription:&errorDesc];
if (plistData) {
[plistData writeToFile:DataPath atomically:YES];
}
nxthomeview = [[HomeView alloc]initWithNibName:#"HomeView" bundle:nil];
[self.navigationController pushViewController:nxthomeview animated:YES];
[nxthomeview release];
}
Firstly you have to parse 1-5-2010 and 7-5-2010 to NSDate type. You can do it with NSDateFormatter:
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"dd-MM-yyyy"];
NSDate *date1 = [formatter dateFromString:#"1-5-2010"];
NSDate *date2 = [formatter dateFromString:#"7-5-2010"];
//difference between dates in miliseconds
NSTimeInterval interval = [date1 timeIntervalSinceDate:date2];
//interval can be positive or negative, depending on the date1 and date2 values
More about date formatters you get from Apple - Date Formatters
Current date can be got by [NSDate date].
If you want to get the current week, day of the week from date(those are called date components) and so on you can check out the Date and Time Programming Guide

NSXMLParser & memory leaks

I am parsing an XML file using a custom class that instanciates & uses NSXMLParser. On the first call everything is fine but on the second, third and later calls Instruments show tens of memory leaks on certain lines inside didEndElement, didEndElement and foundCharacters functions.
I googled it and found some people having this issue, but I didn't find anything that could really help me.
My Parser class looks like this :
Parser.h
#interface XMLParser : NSObject {
NSMutableArray *data;
NSMutableString *currentValue;
NSArray *xml;
NSMutableArray *videos;
NSMutableArray *photos;
NSXMLParser *parser;
NSURLConnection *feedConnection;
NSMutableData *downloadedData;
Content *content;
Video *video;
BOOL nowPhoto;
BOOL nowVideo;
BOOL finished;
BOOL webTV;
}
-(void)parseXML:(NSURL*)xmlURL;
-(int)getCount;
-(NSArray*)getData;
//- (void)handleError:(NSError *)error;
//#property(nonatomic, retain) NSMutableString *currentValue;
#property(nonatomic, retain) NSURLConnection *feedConnection;
#property(nonatomic, retain) NSMutableData *downloadedData;
#property(nonatomic, retain) NSArray *xml;
#property(nonatomic, retain) NSXMLParser *parser;
#property(nonatomic, retain) NSMutableArray *data;
#property(nonatomic, retain) NSMutableArray *photos;
#property(nonatomic, retain) NSMutableArray *videos;
#property(nonatomic, retain) Content *content;
#property(nonatomic, retain) Video *video;
#property(nonatomic) BOOL finished;
#property(nonatomic) BOOL nowPhoto;
#property(nonatomic) BOOL nowVideo;
#property(nonatomic) BOOL webTV;
#end
Parser.m
#import "Content.h"
#import "Video.h"
#import "Parser.h"
#import <CFNetwork/CFNetwork.h>
#implementation XMLParser
#synthesize xml, parser, finished, nowPhoto, nowVideo, webTV;
#synthesize feedConnection, downloadedData, data, content, photos, videos, video;
-(void)parseXML:(NSURL*)xmlURL {
/*
NSURLRequest *req = [NSURLRequest requestWithURL:xmlURL];
self.feedConnection = [[[NSURLConnection alloc] initWithRequest:req delegate:self] autorelease];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
*/
[[NSURLCache sharedURLCache] setMemoryCapacity:0];
[[NSURLCache sharedURLCache] setDiskCapacity:0];
NSXMLParser *feedParser = [[NSXMLParser alloc] initWithContentsOfURL:xmlURL];
//NSXMLParser *feedParser = [[NSXMLParser alloc] initWithData:theXML];
[self setParser:feedParser];
[feedParser release];
[[self parser] setDelegate:self];
[[self parser] setShouldResolveExternalEntities:YES];
[[self parser] parse];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
if ([elementName isEqualToString:#"articles"]) {
self.finished = NO;
self.nowPhoto = NO;
self.nowVideo = NO;
self.webTV = NO;
if (!data) {
NSMutableArray *tmp = [[NSMutableArray alloc] init];
[self setData:tmp];
[tmp release];
return ;
}
}
if ([elementName isEqualToString:#"WebTV"]) {
self.finished = NO;
self.nowPhoto = NO;
self.nowVideo = NO;
self.webTV = YES;
if (!data) {
NSMutableArray *tmp = [[NSMutableArray alloc] init];
[self setData:tmp];
[tmp release];
return ;
}
}
if ([elementName isEqualToString:#"photos"]) {
if (!photos) {
NSMutableArray *tmp = [[NSMutableArray alloc] init];
[self setPhotos:tmp];
[tmp release];
return;
}
}
if ([elementName isEqualToString:#"videos"]) {
if (!videos) {
NSMutableArray *tmp = [[NSMutableArray alloc] init];
[self setVideos:tmp];
[tmp release];
return;
}
}
if ([elementName isEqualToString:#"photo"]) {
self.nowPhoto = YES;
self.nowVideo = NO;
}
if ([elementName isEqualToString:#"video"]) {
self.nowPhoto = NO;
self.nowVideo = YES;
}
if ([elementName isEqualToString:#"WebTVItem"]) {
if (!video) {
Video *tmp = [[Video alloc] init];
[self setVideo:tmp];
[tmp release];
}
NSString *videoId = [attributeDict objectForKey:#"id"];
[[self video] setVideoId:[videoId intValue]];
}
if ([elementName isEqualToString:#"article"]) {
if (!content) {
Content *tmp = [[Content alloc] init];
[self setContent:tmp];
[tmp release];
}
NSString *contentId = [attributeDict objectForKey:#"id"];
[[self content] setContentId:[contentId intValue]];
return;
}
if ([elementName isEqualToString:#"category"]) {
NSString *categoryId = [attributeDict objectForKey:#"id"];
NSString *parentId = [attributeDict objectForKey:#"parent"];
[[self content] setCategoryId:[categoryId intValue]];
[[self content] setParentId:[parentId intValue]];
categoryId = nil;
parentId = nil;
return;
}
if ([elementName isEqualToString:#"vCategory"]) {
NSString *categoryId = [attributeDict objectForKey:#"id"];
NSString *parentId = [attributeDict objectForKey:#"parent"];
[[self video] setCategoryId:[categoryId intValue]];
[[self video] setParentId:[parentId intValue]];
categoryId = nil;
parentId = nil;
return;
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if (!currentValue) {
currentValue = [[NSMutableString alloc] initWithCapacity:1000];
}
if (currentValue != #"\n")
[currentValue appendString:string];
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
NSString *cleanValue = [currentValue stringByReplacingOccurrencesOfString:#"\n" withString:#""] ;
if ([elementName isEqualToString:#"articles"]) {
self.finished = YES;
//[content release];
}
if ([elementName isEqualToString:#"article"]) {
[[self data] addObject:[self content]];
[self setContent:nil];
[self setPhotos:nil];
[self setVideos:nil];
/*
[content release];
content = nil;
[videos release];
videos = nil;
[photos release];
photos = nil;
*/
}
if ([elementName isEqualToString:#"WebTVItem"]) {
[[self data] addObject:[self video]];
[self setVideo:nil];
//[video release];
//video = nil;
}
if ([elementName isEqualToString:#"title"]) {
//NSLog(#"Tit: %#",cleanValue);
[[self content] setTitle:cleanValue];
}
if ([elementName isEqualToString:#"vTitle"]) {
[[self video] setTitle:cleanValue];
}
if ([elementName isEqualToString:#"link"]) {
//NSURL *url = [[NSURL alloc] initWithString:cleanValue] ;
[[self content] setUrl:[NSURL URLWithString:cleanValue]];
[[self content] setLink: cleanValue];
//[url release];
//url = nil;
}
if ([elementName isEqualToString:#"vLink"]) {
[[self video] setLink:cleanValue];
[[self video] setUrl:[NSURL URLWithString:cleanValue]];
}
if ([elementName isEqualToString:#"teaser"]) {
NSString *tmp = [cleanValue stringByReplacingOccurrencesOfString:#"##BREAK##" withString:#"\n"];
[[self content] setTeaser:tmp];
tmp = nil;
}
if ([elementName isEqualToString:#"content"]) {
NSString *tmp = [cleanValue stringByReplacingOccurrencesOfString:#"##BREAK##" withString:#"\n"];
[[self content] setContent:tmp];
tmp = nil;
}
if ([elementName isEqualToString:#"category"]) {
[[self content] setCategory:cleanValue];
}
if ([elementName isEqualToString:#"vCategory"]) {
[[self video] setCategory:cleanValue];
}
if ([elementName isEqualToString:#"date"]) {
[[self content] setDate:cleanValue];
}
if ([elementName isEqualToString:#"vDate"]) {
[[self video] setDate:cleanValue];
}
if ([elementName isEqualToString:#"thumbnail"]) {
[[self content] setThumbnail:[NSURL URLWithString:cleanValue]];
[[self content] setThumbnailURL:cleanValue];
}
if ([elementName isEqualToString:#"vThumbnail"]) {
[[self video] setThumbnailURL:cleanValue];
[[self video] setThumbnail:[NSURL URLWithString:cleanValue]];
}
if ([elementName isEqualToString:#"vDirectLink"]){
[[self video] setDirectLink: cleanValue];
}
if ([elementName isEqualToString:#"preview"]){
[[self video] setPreview: cleanValue];
}
if ([elementName isEqualToString:#"thumbnail_position"]){
[[self content] setThumbnailPosition: cleanValue];
}
if ([elementName isEqualToString:#"url"]) {
if (self.nowPhoto == YES) {
[[self photos] addObject:cleanValue];
}
else if (self.nowVideo == YES) {
[[self videos] addObject:cleanValue];
}
}
if ([elementName isEqualToString:#"photos"]) {
[[self content] setPhotos:[self photos]];
//[photos release];
//photos = nil;
self.nowPhoto = NO;
}
if ([elementName isEqualToString:#"videos"]) {
[[self content] setVideos:[self videos]];
//[videos release];
//videos = nil;
self.nowVideo = NO;
}
//[cleanValue release];
//cleanValue = nil;
[currentValue release];
currentValue = nil;
}
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:#"Error" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[alert release];
}
-(NSArray*)getData {
return data;
}
-(int)getCount {
return [data count];
}
- (void)dealloc {
[parser release];
//[data release];
//[photos release];
//[videos release];
//[video release];
//[content release];
[currentValue release];
[super dealloc];
}
#end
Somewhere in my code, I create an instance of this class :
XMLParser* feed = [[XMLParser alloc] init];
[self setRssParser:feed];
[feed release];
// Parse feed
NSString *url = [NSString stringWithFormat:#"MyXMLURL"];
[[self rssParser] parseXML:[NSURL URLWithString:url]];
Now the problem is that after the first (which has zero leaks), instruments shows leaks in too many parts like this one (they are too much to enumerate them all, but all the calls look the same, I made the leaking line bold) :
in didEndElement :
if ([elementName isEqualToString:#"link"]) {
// THIS LINE IS LEAKING => INSTRUMENTS SAYS IT IS A NSCFString LEAK
[self content] setUrl:[NSURL URLWithString:cleanValue]];
[[self content] setLink: cleanValue];
}
Any idea how to fix this pealse ?
Could this be the same problem as the one mentioned (as an apple bug) by Lee Amtrong here :NSXMLParser Leaking
-(BOOL)fetchAndParseRss{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
//To suppress the leak in NSXMLParser
[[NSURLCache sharedURLCache] setMemoryCapacity:0];
[[NSURLCache sharedURLCache] setDiskCapacity:0];
NSURL *url = [NSURL URLWithString:GALLERY_FEED];
BOOL success = NO;
NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
[parser setDelegate:self];
[parser setShouldProcessNamespaces:YES];
[parser setShouldReportNamespacePrefixes:YES];
[parser setShouldResolveExternalEntities:NO];
success = [parser parse];
[parser release];
[pool drain];
return success;
}
As found on this page, you can do the following to get rid of the leaks as well (I've found that you don't need the setMemoryCapacity or setDiskCapacity calls):
NSData *xml = [NSData
dataWithContentsOfURL: [NSURL
URLWithString:#"http://some-xml-url.com/my.xml"]];
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xml];