Memory: object not release after view controller dismiss, with ARC
Asked Answered
A

6

13

I have 2 view controller,

FirstViewController - > SecondViewController via

[self presentViewController:SVC animated:YES completion:nil];

memory graph

on SecondViewContrller when I do

[self dismissViewControllerAnimated:YES completion:nil];

enter image description here

My question is, Why is the objects not release on secondViewController after I dismiss this viewcontroller. As you can see on the graph It didn't go down after dismiss. BTW whats the best way to release/dismiss a ViewController?

[EDIT]

I NSLog a message on dealloc method on every VC, When I start from FVC->SVC->[dismiss SVC]. this is my logs

enter image description here

Archaeo answered 29/11, 2013 at 7:34 Comment(10)
did you alloc the viewcontroller properly. give your viewcontroller init alloc codeAixlachapelle
SecondViewController *SVC = [[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:nil];Archaeo
You can implement the dealloc method in your second view controller and put a breakpoint in there (or an NSLog). ARC does not mean immediate releasing.Blimp
set property for viewcontrollerAixlachapelle
@MarcMosby It seems it did not went through dealloc method. I though ARC will take care of this. What should I do in dealloc?Archaeo
@iDev what do you mean set property for vc?Archaeo
@MarcMosby Oh! my bad! It went through dealloc method. I forgot to enable the breakpoint sorry.Archaeo
Mostly you should do nothing in there. This is a good place to unregister observers, but don't set properties to nil or stuff like that (ARC does that for you). If there is no need to dealloc your VC, then ARC won't do it. If it went through dealloc, then I'd say it's released.Blimp
@MarcMosby yeah, but I'm wondering how was memory not release after dismissing? From What I've search on, if you dismiss the VC all object/properties under it would automatically release also..Archaeo
@MarcMosby I tried to log a message on dealloc on each FVC and SVC. when I start with FVC->SVC->[SVC dismiss] the log is these:FVC-dealloc,SVC-dealloc,FVC-deallocArchaeo
I
8

This can be pretty rough stuff. I had similar issues before. Search your code and see if you have strong or wrong references to objects.

One of my top mistakes (and what I have seen on the internet hundreds of times) are delegate properties. I wrote them like @property (nonatomic, retain) id<protocol>delegate; for quite a long time as I realized that if I do so, the delegated object does not get released. One have to use assign in this case.

Hope that help you...

Isleen answered 29/11, 2013 at 8:32 Comment(1)
Hi thanks for your thoughts, BUT in my case I didn't do any delegate,outlet,protocol etc. this is just a simple view controller. My point in this is to really check the memory management when dismissing VC's.Archaeo
M
2

I have made some investigation with this behavior.

FirstViewController.m

 #import "FirstViewController.h"  
 #import "SecondViewController.h"

@interface FirstViewController ()

@end

@implementation FirstViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
    // Custom initialization
}
  return self;
}

-(void)dealloc {
    NSLog(@"First Dealloc");

}

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor redColor];
    UIButton *pressMe=[UIButton buttonWithType:UIButtonTypeCustom];
    pressMe.frame = CGRectMake(0, 0, 100, 40);
    pressMe.center = self.view.center;
    [pressMe setTitle:@"PressMe" forState:UIControlStateNormal];
    [pressMe addTarget:self action:@selector(pressMeAction:)             
    forControlEvents:UIControlEventTouchUpInside];
     [self.view addSubview:pressMe];

// Do any additional setup after loading the view.
 }

 - (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

-(void) pressMeAction:(id) sender
{
    SecondViewController *svc = [[SecondViewController alloc] init];
    [self presentViewController:svc animated:YES completion:nil];
    NSLog(@"Present Second");
}

@end

SecondViewController.m

is pretty the same except

-(void) pressDissmissButtonAction:(id) sender
{
    [self dismissViewControllerAnimated:YES completion:nil];
    NSLog(@"Dismiss Second");
}

and this is Allocation dynamics enter image description here

As you can see after pressMeButtonAction invoked secondViewController allocated and after pressDissmissButtonAction invoked secondViewController is successfully deallocated.

BUT: Most of the time it deallocated immediately, but if you present and dismiss it very quickly (twice a second or so), dellocation not fired immediately, but after a while.

I Assume that this is by design implementation of ARC deallocation procedure. Not sure.

Mon answered 29/11, 2013 at 8:41 Comment(7)
You cannot implement the -dealloc method with ARC enabledIsleen
This is not correct. You must not invoke delloc on super when using ARC. developer.apple.com/library/mac/documentation/Cocoa/Reference/…Mon
does your NSlog on dealloc method on FirstVC came out?Archaeo
No it not, coz this controller is a root controller.Mon
Sorry, I thought I couldn't compile with implemented -dealloc methodIsleen
I tried to recreate your VC's when I dismiss the SVC, how come it'll wend through dealloc on FVC?Archaeo
@Bodz Well it depends on your needs, in my solution the FVC is root, so you can't dismiss it, if you what to check that it dealloc try to create another root controller and let this controller present both FVC and SVC. But I think this is not that you try to achieve.Mon
T
0

try this ...

[self presentViewController:SVC animated:YES completion:nil];

SVC = nil;
Thurston answered 29/11, 2013 at 8:26 Comment(1)
You cannot send release messages when using ARC.Isleen
P
0

After spending many hours on this, I finally found a missing piece of the puzzle: Not only do you have to set any strong references to the ViewController to nil, you also have to invalidate any timers and be aware of block retain cycles. Any time you use self in a block you create a retain cycle! Instead you should declare a variable like so

__unsafe_unretained ViewController *weakSelf = self; 

and use it instead of self in the block.

Prison answered 4/2, 2016 at 23:54 Comment(1)
Thanks for this info. Could you provide a screenshot for the memory chart where in it will go down once you dismiss the SecondViewControllerArchaeo
L
0

Check all IBOutlets in your application. There might be "strong" property assigned to them. Make them "weak". For example, an IBOulet should be like this:

@property (weak, nonatomic) IBOutlet UILabel *myLabel;

Check all delegates (if any) in your application. Every delegate should be like this:

@property (nonatomic, assign) id <yourProtocol> delegate;

Note that, it takes some amount of time for ARC to recover memory.

Lilybel answered 3/8, 2016 at 4:59 Comment(0)
R
0

Timers were the issue in my case. Added timer invalidate to viewWillDisappear and the view controllers were then released.

Regine answered 25/1, 2017 at 16:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.