内存泄漏&回到相册列表时应用崩溃

时间:2012-02-05 20:36:41

标签: iphone xcode three20

我正在使用three20来创建图像查看器。首先我要从sql db创建专辑列表,当用户选择任何专辑时,其url字符串将传递给此代码,该代码使用XML Parser在网络上创建可用图片的thum。一切正常,但当用户返回专辑列表并选择另一个专辑。应用程序崩溃'主题1:程序收到信号:“EXC + BAD_ACCESS” main.m 。加上XCode产品分析可以在viewDidLoad中创建photoSource时发生潜在的内存泄漏。这是代码

#import "AlbumController.h"
#import "PhotoSource.h"
#import "Photo.h"
#import "AlbumInfo.h"
#import "AlbumDatabase.h"

@implementation AlbumController

@synthesize albumName;
@synthesize urlAddress;

@synthesize images;

- (void)viewDidLoad
{
    [super viewDidLoad];
   // NSLog(@"%@", self.urlAddress);

    [self createPhotos]; // method to set up the photos array
    self.photoSource = [[PhotoSource alloc]
                        initWithType:PhotoSourceNormal
                        title:self.albumName
                        photos:images
                        photos2:nil];


    self.navigationController.navigationBar.tintColor = [UIColor blackColor];

}

- (void)viewDidUnload
{
    [super viewDidUnload];

    // release and set to nil
}

-(void)createPhotos
{
    if ([stories count] == 0)
    {

        NSString *path = self.urlAddress;
        [self parseXMLFileAtURL:path];
    }


    images = [NSMutableArray arrayWithCapacity:[stories count]]; // needs to be mutable

    for (int i = 0; i < [stories count]; i++)
    {        
        NSString *img = [[stories objectAtIndex:i] objectForKey:@"image"];
        img = [img stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];

        //NSString * caption = [[stories objectAtIndex:i] objectForKey:@"caption"];
        //caption = [caption stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];

        [images addObject:[[[Photo alloc] initWithURL:img smallURL:img size:CGSizeMake(320, 212)] autorelease]];
    }
}


#pragma mark -
#pragma mark XML Parser Implementation

- (void)parserDidStartDocument:(NSXMLParser *)parser{   
    //NSLog(@"found file and started parsing");
}

- (void)parseXMLFileAtURL:(NSString *)URL
{   
    stories = [[NSMutableArray alloc] init];

    //you must then convert the path to a proper NSURL or it won't work
    NSURL *xmlURL = [NSURL URLWithString:URL];

    // here, for some reason you have to use NSClassFromString when trying to alloc NSXMLParser, otherwise you will get an object not found error
    // this may be necessary only for the toolchain
    rssParser = [[NSXMLParser alloc] initWithContentsOfURL:xmlURL];

    // Set self as the delegate of the parser so that it will receive the parser delegate methods callbacks.
    [rssParser setDelegate:self];

    // Depending on the XML document you're parsing, you may want to enable these features of NSXMLParser.
    [rssParser setShouldProcessNamespaces:NO];
    [rssParser setShouldReportNamespacePrefixes:NO];
    [rssParser setShouldResolveExternalEntities:NO];
    [rssParser parse];
}

- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
    NSString * errorString = [NSString stringWithFormat:@"Unfortunately it is not possible to load Pictures. Please check Internet Connection. (Error code %i )", [parseError code]];
    //NSLog(@"error parsing XML: %@", errorString);

    UIAlertView * errorAlert = [[UIAlertView alloc] initWithTitle:@"Failed to load the feed." message:errorString 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
{           
    //NSLog(@"found this element: %@", elementName);
    currentElement = [elementName copy];
    if ([elementName isEqualToString:@"item"]) {
        // clear out our story item caches...
        item = [[NSMutableDictionary alloc] init];
        currentCaption = [[NSMutableString alloc] init];
        //currentThumbnail = [[NSMutableString alloc] init];
        currentImage = [[NSMutableString alloc] init];
    }
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{     
    //NSLog(@"ended element: %@", elementName);
    if ([elementName isEqualToString:@"item"]) {
        // save values to an item, then store that item into the array...

        //[item setObject:currentThumbnail forKey:@"thumbnail"];
        //[item setObject:currentCaption forKey:@"caption"];
        [item setObject:currentImage forKey:@"image"];

        [stories addObject:[[item copy] autorelease]];
    }   
}

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

    // save the characters for the current item...
    if ([currentElement isEqualToString:@"thumbnail"]) {
        //[currentThumbnail appendString:string];
    }// else if ([currentElement isEqualToString:@"caption"]) {
        //[currentCaption appendString:string];
    //}
    else if ([currentElement isEqualToString:@"image"]) {
        [currentImage appendString:string];
    }
}

- (void)parserDidEndDocument:(NSXMLParser *)parser {
    NSLog(@"all done!");
    NSLog(@"stories array has %d items", [stories count]);
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
    if (toInterfaceOrientation == UIInterfaceOrientationPortrait || 
        toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
        toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)
    {
        return YES;
    }
    else 
    {
        return NO;
    }

}



#pragma mark -
#pragma mark Memory Management

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
    // Release anything that's not essential, such as cached data
}

- (void)dealloc {

    [currentElement release];
    [rssParser release];
    [stories release];
    [item release];
    [currentCaption release];
    //[currentThumbnail release];
    [currentImage release];
    [images release];
    [stories release];

    [super dealloc];
}

@end

这里是推送此视图的didSelectRowAtIndexPath

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{    
    AlbumInfo *info = [_albumInfos objectAtIndex:indexPath.row];
    AlbumController *albumController = [[AlbumController alloc] init];

    albumController.urlAddress = info.address;
    albumController.albumName = info.name;
    [self.navigationController pushViewController:albumController animated:YES];
    [albumController release];   
}

以下是AlbumController.h的代码

#import <Foundation/Foundation.h>
#import "Three20/Three20.h"

@interface AlbumController : TTThumbsViewController <NSXMLParserDelegate>
{
    NSString *albumName;
    NSString *urlAddress;

    // images
    NSMutableArray *images;

    // parser
    NSXMLParser * rssParser;
    NSMutableArray * stories;
    NSMutableDictionary * item;
    NSString * currentElement;
    NSMutableString * currentImage;
    NSMutableString * currentCaption;

}

@property (nonatomic, strong) NSString *albumName;
@property (nonatomic, strong) NSString *urlAddress;

@property (nonatomic, retain) NSMutableArray *images;

- (void)createPhotos;
- (void)parseXMLFileAtURL:(NSString *)URL;

@end

使用了本教程http://www.raywenderlich.com/1430/how-to-use-the-three20-photo-viewer

需要帮助解决此内存泄漏问题并需要知道崩溃的原因。

由于

2 个答案:

答案 0 :(得分:0)

简单。在Xcode 4.0+中,只需单击“运行”图标上的“按住”,然后按“配置文件”。它会打开乐器,你会想要僵尸。然后将您的应用程序导航到之前发生崩溃的位置,这次,它将显示在带有调用者的Instruments中,以及有关它的所有信息。

答案 1 :(得分:0)

viewDidLoad中的内存泄漏是由以下行引起的:

self.photoSource = [[PhotoSource alloc]
                    initWithType:PhotoSourceNormal
                    title:self.albumName
                    photos:images
                    photos2:nil];

[PhotoSource alloc]返回您拥有的对象(保留计数为+1)。 initWithType:title:photos:photos2:不会更改保留计数。

所以viewDidLoad留下了它拥有的对象,但没有指向它的指针。要平衡alloc,您应该发送一个自动释放消息:

self.photoSource = [[[PhotoSource alloc]
                     initWithType:PhotoSourceNormal
                     title:self.albumName
                     photos:images
                     photos2:nil] autorelease];