NSXMLParser 在第二次调用时使我的应用程序崩溃(泄漏)

发布于 2024-11-17 17:41:01 字数 8483 浏览 0 评论 0原文

我在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

猫弦 2024-11-24 17:41:01

我认为您在 XMLController 中缺少 dealloc 方法。

此外,如果 xmlcontretaincopy,self.xmlcont = [[XMLController alloc] init]; 可能会导致内存泄漏 属性。在 dealloc 中,您应该更喜欢使用不带点语法的 [xmlcont release];

可能还会有更多问题,但这些可能会是一个良好的开端。

I think you are missing a dealloc method in your XMLController.

Also, self.xmlcont = [[XMLController alloc] init]; might be a memory leak if xmlcont is a retain or copy property. In dealloc, you should prefer to do [xmlcont release]; without dot syntax.

There might be more problems, but these bits could make a good start.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文