NSXMLParser 在第二次调用时使我的应用程序崩溃(泄漏)
我在 XCode 4/Objective C 和我的 NSXMLParser 上遇到了一个大问题:
我有一个 Tabbar 应用程序,在一个选项卡上有一个 NSXMLParser,所以在第一次调用时, ...当单击/触摸选项卡时, NSXMLParser 解析我的数据 进入表格视图。但是,如果第二次单击/触摸该选项卡, 解析器/应用程序会产生很大的内存泄漏,如果这还不够,它 在 iPhone(不是模拟器)上崩溃。
也许你们中的任何人都有任何想法。我听说有一个解决方法,但我有 不知道如何实现这一点。欢迎任何示例代码等。
我希望你能帮助我。 谢谢
XMLController.h
#import "XMLController.h"
#import "Tabelle.h"
@implementation XMLController
@synthesize table;
-(id) loadXMLbyURL:(NSString *)urlString{
table = [[NSMutableArray alloc] init];
NSURL *url= [NSURL URLWithString:urlString];
NSData *xmlData = [NSData dataWithContentsOfURL:url];
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xmlData];
parser.delegate = self;
[parser setShouldProcessNamespaces:NO];
[parser setShouldReportNamespacePrefixes:NO];
[parser setShouldResolveExternalEntities:NO];
[parser parse];
[parser release];
return self;
}
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)
namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if([elementName isEqualToString:@"team"])
{
[currentNodeContent setString:nil];
currentTabelle = [[Tabelle alloc] init];
currentNodeContent = [[NSMutableString alloc]init];
}
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)
namespaceURI qualifiedName:(NSString *)qName
{
NSString *theContent = [currentNodeContent stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; //
[currentNodeContent setString:@""];
if([elementName isEqualToString:@"pos"])
{
currentTabelle.place = theContent;
}
if([elementName isEqualToString:@"name"])
{
currentTabelle.Name = theContent;
}
if([elementName isEqualToString:@"w"])
{
currentTabelle.wins = theContent;
}
if([elementName isEqualToString:@"l"])
{
currentTabelle.losses = theContent;
}
if([elementName isEqualToString:@"pct"])
{
currentTabelle.winpct = theContent;
}
if([elementName isEqualToString:@"gb"])
{
currentTabelle.GamesBehind = theContent;
}
if([elementName isEqualToString:@"team"])
{
[table addObject:currentTabelle];
[currentTabelle release];
currentTabelle = nil;
[currentNodeContent release];
currentNodeContent = nil;
}
}
-(void) parserDidEndDocument:(NSXMLParser *)nparser
{
}
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
//currentNodeContent = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
[currentNodeContent appendString:string];
}
@end
#
以及我调用它的类:
#import "TabellenController.h"
#import "Tabelle.h"
#import "Baseball_DeutschlandAppDelegate.h"
#import "CustomCell.h"
@implementation TabellenController
@synthesize xmlcont, ergebnisTabelle;
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad {
//Abfragen nach der Liga (mit Dateiladen)
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//make a file name to write the data to using the documents directory:
NSString *fileName = [NSString stringWithFormat:@"%@/CellContent.txt",
documentsDirectory];
NSString *content = [[NSString alloc] initWithContentsOfFile:fileName
usedEncoding:nil
error:nil];
self.xmlcont = [[XMLController alloc] init];
if ([content isEqualToString:@"1. Bundesliga"]){
if(pageNumber == 0){
[self.xmlcont loadXMLbyURL:@"http://results.baseball-softball.de/extern/standing.php?l=12&xml"];
}
if(pageNumber == 1){
[self.xmlcont loadXMLbyURL:@"http://results.baseball-softball.de/extern/standing.php?l=11&xml"];
}
}if ([content isEqualToString:@"2. Bundesliga"]){
if(pageNumber == 0){
[self.xmlcont loadXMLbyURL:@"http://results.baseball-softball.de/extern/standing.php?l=22&xml"];
}
if(pageNumber == 1){
[self.xmlcont loadXMLbyURL:@"http://results.baseball-softball.de/extern/standing.php?l=21&xml"];
}
}if ([content isEqualToString:@"Regionalligen"]){
if(pageNumber == 0){
[self.xmlcont loadXMLbyURL:@"http://results.baseball-softball.de/extern/standing.php?l=31&xml"];
}
if(pageNumber == 1){
[self.xmlcont loadXMLbyURL:@"http://results.baseball-softball.de/extern/standing.php?l=32&xml"];
}
if(pageNumber == 2){
[self.xmlcont loadXMLbyURL:@"http://results.baseball-softball.de/extern/standing.php?l=33&xml"];
}
if(pageNumber == 3){
[self.xmlcont loadXMLbyURL:@"http://results.baseball-softball.de/extern/standing.php?l=34&xml"];
}
}
[content release];
[super viewDidLoad];
}
- (id)initWithPageNumber:(int)page{
pageNumber = page;
return self;
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
/*NSMutableArray *ar = [xmlcont table];
NSInteger *sections;
for (int i = 0; i < [ar count]; i++){
for (int j = (i+1); j < [ar count]; j++){
}
}*/
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
NSMutableArray *ar = [xmlcont table];
return [ar count];
}
- (NSString *)tableview:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [NSString stringWithFormat:@"# Team W L AVG GB"];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"CustomCell";
CustomCell *cell = (CustomCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
for (id currentObject in topLevelObjects){
if ([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (CustomCell *) currentObject;
break;
}
}
}
// Configure the cell...
NSMutableArray *cont = [xmlcont table];
Tabelle *current = [cont objectAtIndex:indexPath.row];
cell.place.text = [NSString stringWithFormat:@"%@.", [current place]];
cell.team.text = [NSString stringWithFormat:@"%@", [current Name]];
cell.wins.text = [NSString stringWithFormat:@"%@", [current wins]];
cell.losses.text = [NSString stringWithFormat:@"%@", [current losses]];
cell.winpct.text = [NSString stringWithFormat:@"%@", [current winpct]];
cell.gb.text = [NSString stringWithFormat:@"%@", [current GamesBehind]];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 35.0f;
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Navigation logic may go here. Create and push another view controller.
/*<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:@"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];*/
}
#pragma mark -
#pragma mark Memory management
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Relinquish ownership any cached data, images, etc. that aren't in use.
}
- (void)viewDidUnload {
NSLog(@"View verschwindet1");
}
- (void)dealloc {
[self.xmlcont release];
[super dealloc];
}
@end
i have a big Problem on XCode 4/Objective C and my NSXMLParser:
I got a Tabbar App with a NSXMLParser on one Tab, so on the first call,
...when the Tab becomes clicked/touched, the NSXMLParser parses me Data
into a tableview. But, if the tab gets clicked/touched a second time,
the Parser/app creates a big Memory leak, and if thats not enough, it
crashes on the iphone (not simulator).
Maybe any of you have any ideas. I heard about a workaround but i have
no idea how to realize that. Any sample code etc. is welcome.
I hope you can help me.
thanks
XMLController.h
#import "XMLController.h"
#import "Tabelle.h"
@implementation XMLController
@synthesize table;
-(id) loadXMLbyURL:(NSString *)urlString{
table = [[NSMutableArray alloc] init];
NSURL *url= [NSURL URLWithString:urlString];
NSData *xmlData = [NSData dataWithContentsOfURL:url];
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xmlData];
parser.delegate = self;
[parser setShouldProcessNamespaces:NO];
[parser setShouldReportNamespacePrefixes:NO];
[parser setShouldResolveExternalEntities:NO];
[parser parse];
[parser release];
return self;
}
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)
namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if([elementName isEqualToString:@"team"])
{
[currentNodeContent setString:nil];
currentTabelle = [[Tabelle alloc] init];
currentNodeContent = [[NSMutableString alloc]init];
}
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)
namespaceURI qualifiedName:(NSString *)qName
{
NSString *theContent = [currentNodeContent stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; //
[currentNodeContent setString:@""];
if([elementName isEqualToString:@"pos"])
{
currentTabelle.place = theContent;
}
if([elementName isEqualToString:@"name"])
{
currentTabelle.Name = theContent;
}
if([elementName isEqualToString:@"w"])
{
currentTabelle.wins = theContent;
}
if([elementName isEqualToString:@"l"])
{
currentTabelle.losses = theContent;
}
if([elementName isEqualToString:@"pct"])
{
currentTabelle.winpct = theContent;
}
if([elementName isEqualToString:@"gb"])
{
currentTabelle.GamesBehind = theContent;
}
if([elementName isEqualToString:@"team"])
{
[table addObject:currentTabelle];
[currentTabelle release];
currentTabelle = nil;
[currentNodeContent release];
currentNodeContent = nil;
}
}
-(void) parserDidEndDocument:(NSXMLParser *)nparser
{
}
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
//currentNodeContent = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
[currentNodeContent appendString:string];
}
@end
#
And the class where i call it:
#import "TabellenController.h"
#import "Tabelle.h"
#import "Baseball_DeutschlandAppDelegate.h"
#import "CustomCell.h"
@implementation TabellenController
@synthesize xmlcont, ergebnisTabelle;
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad {
//Abfragen nach der Liga (mit Dateiladen)
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//make a file name to write the data to using the documents directory:
NSString *fileName = [NSString stringWithFormat:@"%@/CellContent.txt",
documentsDirectory];
NSString *content = [[NSString alloc] initWithContentsOfFile:fileName
usedEncoding:nil
error:nil];
self.xmlcont = [[XMLController alloc] init];
if ([content isEqualToString:@"1. Bundesliga"]){
if(pageNumber == 0){
[self.xmlcont loadXMLbyURL:@"http://results.baseball-softball.de/extern/standing.php?l=12&xml"];
}
if(pageNumber == 1){
[self.xmlcont loadXMLbyURL:@"http://results.baseball-softball.de/extern/standing.php?l=11&xml"];
}
}if ([content isEqualToString:@"2. Bundesliga"]){
if(pageNumber == 0){
[self.xmlcont loadXMLbyURL:@"http://results.baseball-softball.de/extern/standing.php?l=22&xml"];
}
if(pageNumber == 1){
[self.xmlcont loadXMLbyURL:@"http://results.baseball-softball.de/extern/standing.php?l=21&xml"];
}
}if ([content isEqualToString:@"Regionalligen"]){
if(pageNumber == 0){
[self.xmlcont loadXMLbyURL:@"http://results.baseball-softball.de/extern/standing.php?l=31&xml"];
}
if(pageNumber == 1){
[self.xmlcont loadXMLbyURL:@"http://results.baseball-softball.de/extern/standing.php?l=32&xml"];
}
if(pageNumber == 2){
[self.xmlcont loadXMLbyURL:@"http://results.baseball-softball.de/extern/standing.php?l=33&xml"];
}
if(pageNumber == 3){
[self.xmlcont loadXMLbyURL:@"http://results.baseball-softball.de/extern/standing.php?l=34&xml"];
}
}
[content release];
[super viewDidLoad];
}
- (id)initWithPageNumber:(int)page{
pageNumber = page;
return self;
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
/*NSMutableArray *ar = [xmlcont table];
NSInteger *sections;
for (int i = 0; i < [ar count]; i++){
for (int j = (i+1); j < [ar count]; j++){
}
}*/
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
NSMutableArray *ar = [xmlcont table];
return [ar count];
}
- (NSString *)tableview:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [NSString stringWithFormat:@"# Team W L AVG GB"];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"CustomCell";
CustomCell *cell = (CustomCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
for (id currentObject in topLevelObjects){
if ([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (CustomCell *) currentObject;
break;
}
}
}
// Configure the cell...
NSMutableArray *cont = [xmlcont table];
Tabelle *current = [cont objectAtIndex:indexPath.row];
cell.place.text = [NSString stringWithFormat:@"%@.", [current place]];
cell.team.text = [NSString stringWithFormat:@"%@", [current Name]];
cell.wins.text = [NSString stringWithFormat:@"%@", [current wins]];
cell.losses.text = [NSString stringWithFormat:@"%@", [current losses]];
cell.winpct.text = [NSString stringWithFormat:@"%@", [current winpct]];
cell.gb.text = [NSString stringWithFormat:@"%@", [current GamesBehind]];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 35.0f;
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Navigation logic may go here. Create and push another view controller.
/*<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:@"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];*/
}
#pragma mark -
#pragma mark Memory management
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Relinquish ownership any cached data, images, etc. that aren't in use.
}
- (void)viewDidUnload {
NSLog(@"View verschwindet1");
}
- (void)dealloc {
[self.xmlcont release];
[super dealloc];
}
@end
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为您在
XMLController
中缺少dealloc
方法。此外,如果
xmlcont
是retain
或copy,
属性。在self.xmlcont = [[XMLController alloc] init];
可能会导致内存泄漏dealloc
中,您应该更喜欢使用不带点语法的[xmlcont release];
。可能还会有更多问题,但这些可能会是一个良好的开端。
I think you are missing a
dealloc
method in yourXMLController
.Also,
self.xmlcont = [[XMLController alloc] init];
might be a memory leak ifxmlcont
is aretain
orcopy
property. Indealloc
, you should prefer to do[xmlcont release];
without dot syntax.There might be more problems, but these bits could make a good start.