当手动重载viewDidLoad时如何清除内存并使用viewDidUnload

时间:2011-07-29 07:03:38

标签: iphone memory-management

帮助了解如何使用我的应用程序中的内存来解决问题,可能有另一种方法来实现我的任务。

拥有以下代码:

Constants.h

#import <Foundation/Foundation.h>

extern NSString * const ITEM;
extern NSString * const TITLE;
extern NSString * const IMAGE;
extern NSString * const DESCRIPTION;
extern NSString * const TEXT;

@interface Constants : NSObject
{

}

@end

Constants.m

#import "Constants.h"

@implementation Constants

NSString * const ITEM           = @"item";
NSString * const TITLE          = @"title";
NSString * const IMAGE          = @"image";
NSString * const DESCRIPTION    = @"description";
NSString * const TEXT           = @"text";

 - (void)dealloc
{
    [super dealloc];
}

@end

myNews.h

#import <Foundation/Foundation.h>

@interface myNews : NSObject
{
    NSString *itemTitle;
    NSString *itemImageUrl;
    NSString *itemDescription;
    NSString *itemText;
}

@property (nonatomic, retain) NSString *itemTitle;
@property (nonatomic, retain) NSString *itemImageUrl;
@property (nonatomic, retain) NSString *itemDescription;
@property (nonatomic, retain) NSString *itemText;

@end

myNews.m

#import "myNews.h"

@implementation myNews

@synthesize itemTitle;
@synthesize itemImageUrl;
@synthesize itemDescription;
@synthesize itemText;

@end

XMLController.h

#import <Foundation/Foundation.h>

@class Constants;
@class myNews;

@interface XMLController : NSObject
{
    NSMutableString *currentNodeContent;
    NSMutableArray *newsArray;
    NSXMLParser *parser;
    myNews *currentNew;
}

@property (readonly, retain) NSMutableArray *newsArray;

-(id)loadXMLByURL:(NSString *)urlString;

@end

XMLController.m

#import "XMLController.h"
#import "Constants.h"
#import "myNews.h"

@implementation XMLController

@synthesize newsArray;

-(id)loadXMLByURL:(NSString *)urlString
{
    newsArray = [[NSMutableArray alloc] init];
    NSURL *url = [NSURL URLWithString: urlString];
    parser = [[NSXMLParser alloc] initWithContentsOfURL: url];
    [parser setDelegate:(id)self];
    [parser parse];
    return self;
}

-(void) parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict
{
    if ([elementName isEqualToString: ITEM])
    {
        currentNew = [myNews alloc];
        currentNodeContent = [[NSMutableArray alloc] init];
    }
}

-(void) parser:(NSXMLParser *)parser
didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
{    
    if ([elementName isEqualToString: TITLE])
    {
        currentNew.itemTitle = currentNodeContent;
    }

    if ([elementName isEqualToString: IMAGE])
    {
        currentNew.itemImageUrl = currentNodeContent;
    }

    if ([elementName isEqualToString: DESCRIPTION])
    {
        currentNew.itemDescription = currentNodeContent;
    }

    if ([elementName isEqualToString: TEXT])
    {
        currentNew.itemText = currentNodeContent;
    }

    if ([elementName isEqualToString: ITEM])
    {
        [newsArray addObject:currentNew];
        [currentNew release];
        currentNew = nil;
        [currentNodeContent release];
        currentNodeContent = nil;
    }
}

-(void) parser:(NSXMLParser *)parser
foundCharacters:(NSString *)string
{
    currentNodeContent = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}

@end

myAppDelegate.h

#import <UIKit/UIKit.h>
#import "MainViewController.h"
#import "DetailViewController.h"

@class MainViewController;
@class DetailViewController;

@interface myAppDelegate : NSObject <UIApplicationDelegate>
{
    UIWindow *window;
    UINavigationController *myNavigationController;    
    MainViewController *myMainViewController;
    DetailViewController *myDetailViewController;  
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UINavigationController *myNavigationController;
@property (nonatomic, retain) IBOutlet MainViewController *myMainViewController;
@property (nonatomic, retain) IBOutlet DetailViewController *myDetailViewController;

@end

myAppDelegate.m

#import "myAppDelegate.h"
#import "myNews.h"
#import "MainViewController.h"
#import "DetailViewController.h"

@implementation myAppDelegate

@synthesize window;
@synthesize myNavigationController;
@synthesize myMainViewController;
@synthesize myDetailViewController;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [window addSubview:myNavigationController.view];
    [window makeKeyAndVisible];

    return YES;
}

- (void)dealloc 
{
    [window release];
    [myNavigationController release];
    [myMainViewController release];
    [myDetailViewController release];
    [super dealloc];
}

@end

MainViewController.h

#import <UIKit/UIKit.h>
#import "XMLController.h"

@interface MainViewController : UIViewController
{
    XMLController *xmlcont;
UILabel *myTitleLabel;

// declared here some 10 objects

}

@property (nonatomic, retain) UILabel *myTitleLabel;

@end

MainViewController.m

#import "MainViewController.h"
#import "myNews.h"

@implementation MainViewController

@synthesize myTitleLabel;

- (void)completeRefresh
{       
    [myMainViewController viewDidLoad];
}

- (void)viewDidLoad
{    
    [super viewDidLoad];

UIButton *myRefreshButton = [[UIButton alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 35.0f, 23.0f)];
[myRefreshButton setImage:[UIImage imageNamed:@"ButtonRefresh.png"] forState:UIControlStateNormal];
[myRefreshButton addTarget:self
                        action:@selector(completeRefresh)
                        forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *myRefreshBarButton = [[[UIBarButtonItem alloc] initWithCustomView:myRefreshButton] autorelease];
[self.navigationItem setRightBarButtonItem: myRefreshBarButton];
[myRefreshButton release];

    xmlcont = [[XMLController alloc] loadXMLByURL:@"http://link_to_XML_file.xml"];

    NSLog(@"array = %@", [xmlcont newsArray]);

    for (myNews *oneNew in [xmlcont newsArray]) {

                CGRect frameTitleLabel = CGRectMake(0.0f, 200.0f, 320.0f, 60.0f);
    myTitleLabel = [[UILabel alloc] initWithFrame:frameTitleLabel];
    myTitleLabel.backgroundColor = [UIColor blackColor];
    myTitleLabel.text = [myOneNew itemTitle];
    myTitleLabel.font = [UIFont fontWithName:@"HelveticaNeue-Bold" size: 17.0];
    myTitleLabel.textColor = [UIColor whiteColor];
    [self.view addSubview:myTitleLabel];
    [myTitleLabel release];

    }

}

- (void)viewDidUnload
{
self.myTitleLabel = nil;
    [super viewDidUnload];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

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

@end

在测试过程中,使用Instruments:Activity Monitor的应用程序显示当你点击刷新并调用'completeRefresh'时,重新加载viewDidLoad时不会清除内存(Real Mem),并且每次触摸都会累积并调用'completeRefresh'

也许某人有可能的解决方案?

1 个答案:

答案 0 :(得分:1)

为避免内存泄漏,您需要在dealloc中释放保留的ivars / properties。例如:

<强> myNews.m

- (void)dealloc {
    // Setting these properties to nil releases them because they're (nonatomic, retain)
    self.itemTitle = nil;
    self.itemImageUrl = nil;
    self.itemDescription = nil;
    self.itemText = nil;
    [super dealloc];
}

<强> XMLController.m

- (void)dealloc {
    self.newsArray = nil;
    // These ivars aren't properties so you just have to call release on them
    [currentNodeContent release];
    [parser release];
    [currentNew release];
    [super dealloc];
}

等。为你的所有课程都这样做。