Proper Memory Managment Help

Discussion in 'iOS Programming' started by Theclamshell, Jul 3, 2011.

  1. Theclamshell macrumors 68030

    Joined:
    Mar 2, 2009
    #1
    First let me state I am a noob at this.

    I am making a view based application and everything is going well. One thing I am noticing though is that when the app loads on the phone, each new view I open takes up more memory. The problem is that when i navigate away from that view, no memory is released. I'm not sure if this is normal or not. I used the inspector tool and it did not show any memory leaks but I'm still confused. I will attach my ViewController.H and .M files and if anyone could tell me if there is proper memory management or not that would be great. If there is not proper memory management then could you point me in the right direction. I read some of apples documentation on this and got confused.

    Code:
    
    //
    //  MyappViewController.m
    //  Myapp
    //
    //  Created by Bij on 7/2/11.
    //  Copyright 2011 __MyCompanyName__. All rights reserved.
    //
    
    #import "MyappViewController.h"
    #import "view1.h"
    #import "view2.h"
    #import "view3.h"
    #import "view5.h"
    #import "view6.h"
    #import "view7.h"
    #import "view8.h"
    #import "view9.h"
    
    
    @implementation MyappViewController
    
    - (IBAction)view1:(id)sender
    {
        view1 *second =[[view1 alloc] initWithNibName:nil bundle:nil];
        [self presentModalViewController:second animated:YES];
       
    }
    
    - (IBAction)view2:(id)sender
    {
        view2 *second =[[view2 alloc] initWithNibName:nil bundle:nil];
        [self presentModalViewController:second animated:YES];
    }
    
    - (IBAction)view3:(id)sender
    {
        view3 *second =[[view3 alloc] initWithNibName:nil bundle:nil];
        [self presentModalViewController:second animated:YES];
    }
    
    - (IBAction)view5:(id)sender
    {
        view5 *second =[[view5 alloc] initWithNibName:nil bundle:nil];
        [self presentModalViewController:second animated:YES];
    }
    
    - (IBAction)view6:(id)sender
    {
        view6 *second =[[view6 alloc] initWithNibName:nil bundle:nil];
        [self presentModalViewController:second animated:YES];
    }
    
    - (IBAction)view7:(id)sender
    {
        view7 *second =[[view7 alloc] initWithNibName:nil bundle:nil];
        [self presentModalViewController:second animated:YES];
    }
    
    - (IBAction)view8:(id)sender
    {
        view8 *second =[[view8 alloc] initWithNibName:nil bundle:nil];
        [self presentModalViewController:second animated:YES];
    }
    
    - (IBAction)view9:(id)sender
    {
        view9 *second =[[view9 alloc] initWithNibName:nil bundle:nil];
        [self presentModalViewController:second animated:YES];
    }
    
    
    
    
    
    - (void)dealloc
    {
        [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
    
    /*
    // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    }
    */
    
    - (void)viewDidUnload
    {
        [super viewDidUnload];
        // Release any retained subviews of the main view.
        // e.g. self.myOutlet = nil;
    }
    
    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
    {
        // Return YES for supported orientations
        return (interfaceOrientation == UIInterfaceOrientationPortrait);
    }
    
    
    
    
    @end
    
    
    Here is the .H file:

    Code:
    
    //
    //  MyappViewController.h
    //  Myapp
    //
    //  Created by Bij on 7/2/11.
    //  Copyright 2011 __MyCompanyName__. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    @interface MyappViewController : UIViewController {
        
        
        IBOutlet UIViewController *view1;
        IBOutlet UIViewController *view2;
        IBOutlet UIViewController *view3;
        IBOutlet UIViewController *view4;
        IBOutlet UIViewController *view5;
        IBOutlet UIViewController *view6;
        IBOutlet UIViewController *view7;
        IBOutlet UIViewController *view8;
        IBOutlet UIViewController *view9;
        
        
        
    }
    - (IBAction)view1:(id)sender;
    - (IBAction)view2:(id)sender;
    - (IBAction)view3:(id)sender;
    - (IBAction)view5:(id)sender;
    - (IBAction)view6:(id)sender;
    - (IBAction)view7:(id)sender;
    - (IBAction)view8:(id)sender;
    - (IBAction)view9:(id)sender;
    @end
    
    
     
  2. mfram macrumors 65816

    Joined:
    Jan 23, 2010
    Location:
    San Diego, CA USA
    #2
    Yes, you need to release these views. You called alloc, therefore you must release them. Here's a web page with the rules distilled down: iPhone Memory Management.
     
  3. Theclamshell, Jul 3, 2011
    Last edited: Jul 3, 2011

    Theclamshell thread starter macrumors 68030

    Joined:
    Mar 2, 2009
    #3
    Ok, I put those lines into my code. Here is my ViewController.m file now.

    Code:
    
    //
    //  MyappViewController.m
    //  Myapp
    //
    //  Created by Bij on 7/2/11.
    //  Copyright 2011 __MyCompanyName__. All rights reserved.
    //
    
    #import "MyappViewController.h"
    #import "view1.h"
    #import "view2.h"
    #import "view3.h"
    #import "view5.h"
    #import "view6.h"
    #import "view7.h"
    #import "view8.h"
    #import "view9.h"
    
    
    @implementation MyappViewController
    
    - (IBAction)view1:(id)sender
    {
        view1 *second =[[view1 alloc] initWithNibName:nil bundle:nil];
        [self presentModalViewController:second animated:YES];
        [view1 release];
       
    }
    
    - (IBAction)view2:(id)sender
    {
        view2 *second =[[view2 alloc] initWithNibName:nil bundle:nil];
        [self presentModalViewController:second animated:YES];
        [view2 release];
    }
    
    - (IBAction)view3:(id)sender
    {
        view3 *second =[[view3 alloc] initWithNibName:nil bundle:nil];
        [self presentModalViewController:second animated:YES];
        [view3 release];
    }
    
    - (IBAction)view5:(id)sender
    {
        view5 *second =[[view5 alloc] initWithNibName:nil bundle:nil];
        [self presentModalViewController:second animated:YES];
        [view5 release];
    }
    
    - (IBAction)view6:(id)sender
    {
        view6 *second =[[view6 alloc] initWithNibName:nil bundle:nil];
        [self presentModalViewController:second animated:YES];
        [view6 release];
    }
    
    - (IBAction)view7:(id)sender
    {
        view7 *second =[[view7 alloc] initWithNibName:nil bundle:nil];
        [self presentModalViewController:second animated:YES];
        [view7 release];
    }
    
    - (IBAction)view8:(id)sender
    {
        view8 *second =[[view8 alloc] initWithNibName:nil bundle:nil];
        [self presentModalViewController:second animated:YES];
        [view8 release];
    }
    
    - (IBAction)view9:(id)sender
    {
        view9 *second =[[view9 alloc] initWithNibName:nil bundle:nil];
        [self presentModalViewController:second animated:YES];
        [view9 release];
    }
    
    
    
    
    
    - (void)dealloc
    {
        [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
    
    /*
    // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    }
    */
    
    - (void)viewDidUnload
    {
        [super viewDidUnload];
        // Release any retained subviews of the main view.
        // e.g. self.myOutlet = nil;
    }
    
    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
    {
        // Return YES for supported orientations
        return (interfaceOrientation == UIInterfaceOrientationPortrait);
    }
    
    
    
    
    @end
    
    
    When I run to analyze it shows issues next to each
    [viewname release];

    the issues say "The release method should be sent to instances of class 'viewx' and not the class directly
     
  4. Scott90 macrumors 6502

    Joined:
    Jul 14, 2008
    #4
    You can't release a class, you can only release an instance of a class. The classnames in your example are view1 - view9, but the name of the instance is "second" in every method. Changing your release statements to [second release] should do the trick.
     
  5. xStep macrumors 68000

    Joined:
    Jan 28, 2003
    Location:
    Less lost in L.A.
    #5
    Looks to me like you are confusing the analyzer.

    The convention is that class names begin with an upper case letter. You have your view class names starting with a lower case v. Change them all to upper case. Keep the object names with lower case.
     
  6. Theclamshell thread starter macrumors 68030

    Joined:
    Mar 2, 2009
    #6
    I think I have found a fix. The application is using much less memory usage in instruments. When i release a view, i will now get memory back. I don;t know if what I did was correct but it seems to work. What I did is change

    Code:
    [self presentModalViewController:second animated:YES];
    
    to

    Code:
    [self dismissModalViewControllerAnimated:YES];
    
    The thing is I only did this when I was leaving one view back to a previous page. I tried doing it for all IBActions but when I wanted to open a new view it would not work. I don't know if this solution makes sense but it appears to work and I am very happy.

    I also have [second release] under each action. I will look into the capital V issue later. Thanks for the help everyone and please feel free to chime on whether this solution makes sense or not.
     
  7. jnoxx macrumors 65816

    jnoxx

    Joined:
    Dec 29, 2010
    Location:
    Aartselaar // Antwerp // Belgium
    #7
    It's very confusing what you are doing.
    Calling ModalViewControllers is no problem, as long as you release your pointer.
    You make a pointer in your memory, to store this specific piece of class. And u are not taking 'reponsibility' of releasing, therefore, u need to release the pointer u made --> * pointerName.
    And like they said above me. Class names should start with an Upper case. Like "SecondViewController", "ThirdViewController", "SettingsViewController".

    U are displaying modalViewControllers, everytime u close them. with the line dismissModalViewControllers, some behind the scene wizardry will do it's magic. All for memory management.
    But in your last post you tell us you are Dismissing = removing a modal view from your view, instead of Presenting it.
    Why would u do that. I don't see in any way, how that would affect your App.
    Maybe you should provide some screenshots instead. So you could show us where to guide you.
     
  8. Theclamshell thread starter macrumors 68030

    Joined:
    Mar 2, 2009
    #8
    Thanks for the reply. I'm sorry I can not explain better, as i am a noob at this stuff. I have been watching some objective-c videos though, trying to learn my way around. I will try to explain better what I am doing.

    Here is my View8.M file

    Code:
    //
    //  view8.m
    //  Myapp
    //
    //  Created by Bij on 7/2/11.
    //  Copyright 2011 __MyCompanyName__. All rights reserved.
    //
    
    #import "view8.h"
    #import "MyappViewController.h"
    #import "view1.h"
    #import "view2.h"
    #import "view3.h"
    #import "view4.h"
    #import "view5.h"
    #import "view6.h"
    #import "view7.h"
    #import "view9.h"
    
    
    @implementation view8
    
    -(IBAction)view1:(id)sender
    {
        view1 *second =[[view1 alloc] initWithNibName:nil bundle:nil];
        [self dismissModalViewControllerAnimated:YES];
        [second release];
    }
    
    -(IBAction)view7:(id)sender
    {
        view7 *second =[[view7 alloc] initWithNibName:nil bundle:nil];
        [self presentModalViewController:second animated:YES];
        [self dismissModalViewControllerAnimated:YES];
        [second release];
    }
    
    
    
    - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
    {
        self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
        if (self) {
            // Custom initialization
        }
        return self;
    }
    
    - (void)dealloc
    {
        [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
    {
        [super viewDidLoad];
        // Do any additional setup after loading the view from its nib.
    }
    
    - (void)viewDidUnload
    {
        [super viewDidUnload];
        // Release any retained subviews of the main view.
        // e.g. self.myOutlet = nil;
    }
    
    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
    {
        // Return YES for supported orientations
        return (interfaceOrientation == UIInterfaceOrientationPortrait);
    }
    
    @end 
    
    
    Here is the
    Code:
    -(IBAction)view1:(id)sender  
    code from that file:


    Code:
    
    -(IBAction)view1:(id)sender
    {
        view1 *second =[[view1 alloc] initWithNibName:nil bundle:nil];
        [self dismissModalViewControllerAnimated:YES];
        [second release];
    
    What this action does (or is supposed to do), is go back to the previous view. Basically, I have a home page, MyappViewController.xib which has buttons which lead to other pages which have more buttons. One of those buttons leads to view1 and one of the buttons on view1 leads to view8 which is a page with a textbox and 2 imageviews.

    What I was seeing each time I ran the app in instruments was that each time I would open any new view say, view8, by using:

    Code:
    - (IBAction)view8:(id)sender
    {
        view8 *second =[[view8 alloc] initWithNibName:nil bundle:nil];
        [self presentModalViewController:second animated:YES];
        [second release];
    
    it would eat up memory. I had no problem with this. What I was getting upset by was that when I tried to go back to view1 by using:

    Code:
    [FONT=monospace]- (IBAction)view1:(id)sender
    {
        view1 *second =[[view1 alloc] initWithNibName:nil bundle:nil];
        [self presentModalViewController:second animated:YES];
        [second release];[/FONT]  
    
    It would not free up the memory that was taken up when opening and showing view8, it was like view8 was not being truly closed. I could go back and forth between view 1 and view 8 and the more i did this, the more memory got taken up, even when using the
    Code:
     [second release]; 
    Here is the thought process I went through with the dismissModalViewController

    I tried using dismissModalViewController in
    Code:
    [FONT=monospace]- (IBAction)view1:(id)sender[/FONT] 
    which gave me

    Code:
    -(IBAction)view1:(id)sender
    {
        view1 *second =[[view1 alloc] initWithNibName:nil bundle:nil];
        [self dismissModalViewControllerAnimated:YES];
        [second release];
    }
    
    Now, what I believed this would do was close the current view, (view8) and go back to view1 without reloading view1. This seemed to work and I tried going back and forth between the too and no memory was being leaked. Each time I exited view8, I would get back the memory that had been allocated for it. I eventually changed the

    Code:
    -(IBAction)view1:(id)sender
    
    from:

    Code:
    [FONT=monospace]- (IBAction)view1:(id)sender
    {
        view1 *second =[[view1 alloc] initWithNibName:nil bundle:nil];
        [self presentModalViewController:second animated:YES];
        [view1 release];
    
    [/FONT]
    to:

    Code:
    -(IBAction)view1:(id)sender
    {
        view1 *second =[[view1 alloc] initWithNibName:nil bundle:nil];
        [self dismissModalViewControllerAnimated:YES];
        [second release];
    
    in all of the windows that were being opened through buttonpresses on view1.

    For example, view8.m is cooresponding to view8.xib which is opened by pressing a button on view 1. I also have other files, view9.xib for example which are also opened by buttonpresses on view1.

    In the .M files of view9 and view8, the code to go back to view 1 is:

    Code:
    -(IBAction)view1:(id)sender
    {
        view1 *second =[[view1 alloc] initWithNibName:nil bundle:nil];
        [self dismissModalViewControllerAnimated:YES];
        [second release];
    
    The code in view1 to go to view 8 and view 9 is,

    Code:
    - (IBAction)view8:(id)sender
    {
        view8 *second =[[view8 alloc] initWithNibName:nil bundle:nil];
        [self presentModalViewController:second animated:YES];
        [self dismissModalViewControllerAnimated:YES];
        [second release];
    }
    
    - (IBAction)view9:(id)sender
    {
        view9 *second =[[view9 alloc] initWithNibName:nil bundle:nil];
        [self presentModalViewController:second animated:YES];
        [self dismissModalViewControllerAnimated:YES];
        [second release];
    }
    
    I put

    Code:
     [self presentModalViewController:second animated:YES];
    [self dismissModalViewControllerAnimated:YES];
    
    together because i was hoping it would open view8 or view 9 and then close view1. I think this works because when i open windows non stop, i do not loose memory like I was before.

    Sorry for the long write up and if my explanation is bad. I'm still trying to learn this stuff so I will definitely be bad at the explanations and code for a while.

    I truly appreciate all the help though. I would post screen shots but do not want to due to the fact that the app is still in development and I would rather not disclose it's contents.
     
  9. jnoxx macrumors 65816

    jnoxx

    Joined:
    Dec 29, 2010
    Location:
    Aartselaar // Antwerp // Belgium
    #9
    U just need to think really good if this is your best way of making the app. How u want it to look, and think about the usability for users.
    if the usability is bad, the customers won't like it.
    So that's a quite hard start ;)
    I would suggest.
    In your First view. where you have for example. 8 Button's to load new views.
    But instead of using ModalViewControllers, u should use a navigation based.
    in your first view (make sure it's an Navigation Controller in your IB, if not, send me files in PM. And I will help you out with it.)

    And instead of this -->

    Code:
    -(IBAction)view1:(id)sender
    {
        view1 *second =[[view1 alloc] initWithNibName:nil bundle:nil];
        [self dismissModalViewControllerAnimated:YES];
        [second release];
    }
    Do

    Code:
    -(IBAction)view1:(id)sender
    {
        view1 *second =[[view1 alloc] initWithNibName:@"view1" bundle:nil];
        [self.navigationController pushViewController:second animated:YES];
        [second release];
    }
    and so on.

    Then u should get a navigationbar implemented. And u can just press the Back Button. to go back to the first. or u can implement your own custom backbutton with this code

    Code:
    - (void) goBack {
     [self.navigationController popViewControllerAnimated:YES];
    }
    Then u don't need to mess around with all the modalViewControllers. Because you are misusing it. Or you should consider a tabbased.
    If you have more questions, reply to the thread.
     

Share This Page