Больше утечек на моем NSXMLParser :( - PullRequest
0 голосов
/ 17 августа 2011

Я в конечном итоге овладею этой идеей распределения памяти и развитием iphone, но я изо всех сил. Ниже мой код моего NSXMLParser для твиттера, который я сделал. Он работает нормально и не просачивается примерно до 30 секунд после загрузки кода ... Это расстраивает меня, потому что, как только я закончу этот парсер и без утечек, я буду готов к работе:).

Я просмотрел множество видеоуроков, и мне просто нужна помощь, чтобы просмотреть мой собственный код, чтобы я смог получить представление.

rssParser.m

//
//  rssParser.m
//  template
//
//  Created by Jonathan Pink on 17/08/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "rssParser.h"


@implementation rssParser
@synthesize entries;


-(id)loadXMLData:(NSData *)xml{
    entries = [[NSMutableArray alloc] init];

    xmlParser = [[NSXMLParser alloc] initWithData:xml];
    [xmlParser setDelegate:self];
    [xmlParser parse];

    return self;
}

-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{

    [currentElement release];
    currentElement = [elementName copy];

    if([elementName isEqualToString:@"item"])
    {
        RssData = [[rssData alloc] init];

        currentRssDescription = [[NSMutableString alloc] init];
        currentRssLink = [[NSMutableString alloc] init];
        currentRssPubDate = [[NSMutableString alloc] init];
        currentRssTitle = [[NSMutableString alloc] init];
    }

}


-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{

    if([elementName isEqualToString:@"item"])
    {
        RssData.rssLink = currentRssLink;
        RssData.rssDescription = currentRssDescription;
        RssData.rssPubDate = currentRssPubDate;
        RssData.rssTitle = currentRssTitle;


        NSLog(@"currenttitle = %@",RssData.rssTitle);

    }
    if([elementName isEqualToString:@"item"])
    {
        [entries addObject:RssData];
        RssData = nil;

    }

}

-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{

    if([currentElement isEqualToString:@"title"])
    {
        [currentRssTitle appendString:string];
    }
    else if([currentElement isEqualToString:@"link"])
    {
        [currentRssLink appendString:string];
    }
    else if([currentElement isEqualToString:@"description"])
    {
        [currentRssDescription appendString:string];
    }
    else if([currentElement isEqualToString:@"pubDate"])
    {
        [currentRssPubDate appendString:string];
    }


}

- (void)parserDidEndDocument:(NSXMLParser *)parser {

    NSLog(@"all done!");
    NSLog(@"stories array has %d items", [entries count]);

}

-(void)dealloc{
    [currentElement release];
    [currentRssDescription release];
    [currentRssLink release];
    [currentRssPubDate release];
    [currentRssTitle release];

    [xmlParser release];
    [RssData release];
    [entries release];

    [super dealloc];
}



    @end

и контроллер просмотра Twitter

//
//  TwitterViewController.m
//  template
//
//  Created by Jonathan Pink on 16/08/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "TwitterViewController.h"
#import "ASIHTTPRequest.h"


@implementation TwitterViewController


- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)dealloc
{
    [config release];
    [RssParser release];
    [super dealloc];
}

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

- (void)viewDidLoad
{
    UIBarButtonItem *anotherButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(ProcessAndParse)];          
    self.navigationItem.rightBarButtonItem = anotherButton;
    [anotherButton release];

    numberOfTextRows = 4;
    config = [[Configuration alloc] init];
    [super viewDidLoad];
    [self ProcessAndParse];
    // Uncomment the following line to preserve selection between presentations.
    // self.clearsSelectionOnViewWillAppear = NO;

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem;
}


-(void)ProcessAndParse{

    NSURL *url = [config urlForFeed:@"Twitter"];
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    [request setDelegate:self];
    [request startAsynchronous];

}

- (void)requestFinished:(ASIHTTPRequest *)request
{
    NSData *responseData = [request responseData];
    RssParser = [[rssParser alloc] loadXMLData:responseData];
    [self.tableView reloadData];
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
}

- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{

    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if ([RssParser entries] == 0) {
        return 1;
    }
    else
    {
    return [[RssParser entries]count];
    }

}

/*#define FIXED_HEIGHT_SECTION 18

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    //RSSData *currentEntry = [[rssParser rssEntries] objectAtIndex:indexPath.row];

    CGSize theSize = [[currentEntry rssDescription] sizeWithFont:[UIFont systemFontOfSize:12.0f] constrainedToSize:CGSizeMake(265.0f, 9999.0f) lineBreakMode:UILineBreakModeWordWrap];
    // This gets the size of the rectangle needed to draw a multi-line string
    numberOfTextRows = round(theSize.height / 18);
    // 18 is the size of the font used in the text label
    // This will give us the number of lines in the multi-line string

    if ((indexPath.section == FIXED_HEIGHT_SECTION) || (numberOfTextRows < 2)) {
        return 44;
        // 44 is the default row height; use it for empty or one-line cells (or in other table sections)
    } else {
        return theSize.height + 35;
        // 16 seems to provide a decent space above/below; tweak to taste
    }
}*/

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
    }

    rssData *currententry =[[RssParser entries] objectAtIndex:indexPath.row];

    if ([RssParser entries] == 0) {
        cell.textLabel.text = @"No Records";
    }
    else
    {
        cell.textLabel.text = [currententry rssTitle];
    }

    return cell;
}

/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Return NO if you do not want the specified item to be editable.
    return YES;
}
*/

/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the row from the data source
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }   
    else if (editingStyle == UITableViewCellEditingStyleInsert) {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
    }   
}
*/

/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/

/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Return NO if you do not want the item to be re-orderable.
    return YES;
}
*/

#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];
     */
}

@end

Любая помощь, я буду вечно благодарен! :)

Ответы [ 2 ]

1 голос
/ 17 августа 2011

Эта строка выглядит немного подозрительно

[entries addObject:RssData];
RssData = nil;

Вы отменяете указатель, но не отпускаете то, на что он указывает.Ваш код довольно труден для понимания, потому что вы не следуете некоторым стандартным соглашениям.

Ваш метод init небезопасен, и он должен начинаться с init... Попробуйте:

-(id)initWithXMLData:(NSData *)xml
{
    self = [super init];
    if (self) {
        entries = [[NSMutableArray alloc] init];

        xmlParser = [[NSXMLParser alloc] initWithData:xml];
        [xmlParser setDelegate:self];
        [xmlParser parse];
    }
    return self;
}

Для именования вещей

RssData // Class names should start with uppercase
rssData // variables and ivars should start with lowercase

В противном случае трудно сказать, когда вы работаете с классом или экземпляром класса.

Вам также следует обратить внимание на использование свойств, которые устранят большую часть сложности руководствауправление памятью.

1 голос
/ 17 августа 2011

Вы пытались профилировать свое приложение с помощью инструментов?Если вы используете анализ на предмет утечек памяти должным образом, он прямо скажет вам, где в коде вызвана утечка памяти.

...