Я пишу приложение, которое использует NSXMLParser - и это убивает меня.
Изначально я заставлял парсер загружать фид из Интернета, и он пропускал много памяти, а теперь я где-то читал, что лучше использовать NSURLConnection для загрузки данных, а затем передавать их парсеру. Проблема в том, что у меня все еще есть проблемы с памятью.
У кого-нибудь есть какие-либо советы о том, как заставить эту вещь работать без утечек?
Большое спасибо!
Общая идея такова. Класс RSSParser, вызывается из контроллера CategoriesControl в viewDidLoad. Швы утечки будут происходить в RSSParser, а именно эти строки:
[parser parse] или [parsedItems addObject: [parsedItem copy]];
И утечки появляются, когда я отхожу от контроллера категорий.
//RSSParser.h
#import
#import "Subscriptions.h"
@interface RSSParser : NSObject {
NSMutableArray *parsedItems;
NSMutableDictionary *parsedItem;
NSXMLParser *parser;
NSString *item;
NSString *ititle;
NSString *link;
NSString *description;
NSString *guid;
NSString *pubDate;
}
@property (nonatomic, retain) NSMutableArray *parsedItems;
@property (nonatomic, retain) NSXMLParser *parser;
- (void)fetch:(NSMutableData *)dt;
@end
//RSSParser.m
#import "RSSParser.h"
@implementation RSSParser
@synthesize parser, parsedItems;
- (void)fetch:(NSMutableData *)dt {
parsedItems = [[NSMutableArray alloc] init];
parser = [[NSXMLParser alloc] initWithData:dt];
[parser setDelegate:self];
[parser setShouldProcessNamespaces:NO];
[parser setShouldReportNamespacePrefixes:NO];
[parser setShouldResolveExternalEntities:NO];
[parser parse];
[parser release];
}
- (void)parserDidStartDocument:(NSXMLParser *)parser {
}
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
UIAlertView * errorAlert = [[UIAlertView alloc] initWithTitle:@"Probleme me te dhenat." message:@"Ju lutem provoni te rilidheni me vone." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[errorAlert show];
[errorAlert release];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
item = [[elementName copy] autorelease];
if ([elementName isEqualToString:@"item"]) {
parsedItem = [[[NSMutableDictionary alloc] init] autorelease];
ititle = [[[NSMutableString alloc] init] autorelease];
link = [[[NSMutableString alloc] init] autorelease];
description = [[[NSMutableString alloc] init] autorelease];
guid = [[[NSMutableString alloc] init] autorelease];
pubDate = [[[NSMutableString alloc] init] autorelease];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if ([item isEqualToString:@"title"]) {
ititle = [ititle stringByAppendingString:string];
} else if ([item isEqualToString:@"link"]) {
link = [link stringByAppendingString:string];
} else if ([item isEqualToString:@"description"]) {
description = [description stringByAppendingString:string];
} else if ([item isEqualToString:@"guid"]) {
guid = [guid stringByAppendingString:string];
} else if ([item isEqualToString:@"pubDate"]) {
pubDate = [pubDate stringByAppendingString:string];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:@"item"]) {
if (![ititle isEqualToString:@""]) { [parsedItem setObject:ititle forKey:@"title"]; }
if (![link isEqualToString:@""]) { [parsedItem setObject:link forKey:@"link"]; }
if (![description isEqualToString:@""]) { [parsedItem setObject:description forKey:@"description"]; }
if (![guid isEqualToString:@""]) { [parsedItem setObject:guid forKey:@"guid"]; }
if (![pubDate isEqualToString:@""]) { [parsedItem setObject:pubDate forKey:@"pubDate"]; }
[parsedItems addObject:[parsedItem copy]];
}
}
- (void)parserDidEndDocument:(NSXMLParser *)parser {
}
@end
*****************************************
//CategoriesController.m
- (void)viewDidLoad {
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://www.ikub.al/RssCategory.aspx?catId=%@", address]]];
connection = [NSURLConnection connectionWithRequest:request delegate:self];
if (connection) {
downloadedData = [[NSMutableData data] retain];
} else {
NSLog(@"Cannot get the data stream.");
}
if ([address length] > 0) {
UIBarButtonItem *subscribeButton = [[UIBarButtonItem alloc] initWithTitle:@"Abonohu" style:UIBarButtonItemStyleBordered target:self action:@selector(newSubscription)];
self.navigationItem.rightBarButtonItem = subscribeButton;
[subscribeButton release];
}
[super viewDidLoad];
}
- (void)connection:(NSURLConnection *)theConnection didReceiveResponse:(NSURLResponse *)response {
[downloadedData setLength:0];
}
- (void)connection:(NSURLConnection *)theConnection didReceiveData:(NSData *)data {
[downloadedData appendData:data];
}
- (void)connection:(NSURLConnection *)theConnection didFailWithError:(NSError *)error {
UIAlertView * errorAlert = [[UIAlertView alloc] initWithTitle:@"Probleme me lidhjen." message:@"Ju lutemi te kontrolloni lidhjen tuaj WiFi, GPRS/EDGE/3G." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[errorAlert show];
[errorAlert release];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)theConnection {
parser = [[RSSParser alloc] init];
[parser fetch:downloadedData];
parsedItems = [parser.parsedItems copy];
[parser.parsedItems release];
[categoriesTable reloadData];
[parser release];
}