Reputation: 12621
Can a child view controller "dismiss itself?" .....
You have a view controller "RedMessage". You have an ordinary strong property for it ...
@property (strong) RedMessage *red;
You add it ("modally") on top of your current VC...
self.red = (RedMessage *)[self.storyboard
instantiateViewControllerWithIdentifier:@"RedMessageID"];
self.red.view.frame = self.view.frame;
[self.view addSubview:self.red.view];
[self addChildViewController:self.red];
[self.red didMoveToParentViewController:self];
To get rid of it later, do this
[self.red willMoveToParentViewController:nil];
[self.red.view removeFromSuperview];
[self.red removeFromParentViewController];
BUT IN FACT, do you need to do this??
[rm willMoveToParentViewController:nil];
[rm.view removeFromSuperview];
[rm removeFromParentViewController];
rm = nil;
Do you need the "= nil;" ?
Note that this question is critical, because: if you do NOT HAVE TO nil it, you can then do the following inside the new view controller...
-(void)dismissMyselfCompletely
{
[self willMoveToParentViewController:nil];
[self.view removeFromSuperview];
[self removeFromParentViewController];
}
Which is extremely convenient.
In short, if you do that inside the new top view controller - will it "work", does it release the VC?
When removeFromParentViewController happens, does the parent VC understand it can release self.red?
Upvotes: 10
Views: 8857
Reputation: 12621
After considerable testing, we found that it appears to be the case that:
it does go away and is not retained.
We add the VC on top like this (just in the usual way you add a "modal" VC on top...)
-(void)showOverlay:(NSDictionary*)dict
{
Red *rr = (Red *)[self.storyboard
instantiateViewControllerWithIdentifier:@"RedID"];
rr.view.frame = self.view.bounds;
[self.view addSubview:rr.view];
[self addChildViewController:rr];
[rr didMoveToParentViewController:self];
[rr useThisData:dict];
}
Note that there's no Property holding rr - it is just created and added on the fly in that category.
Inside "Red" we get rid of it just like this...
-(void)dismiss:(UITapGestureRecognizer *)sender
{
[self.view exitLeftSmoothly:0 then:^
{
[self willMoveToParentViewController:nil];
[self.view removeFromSuperview];
[self removeFromParentViewController];
}];
}
(exitLeft is just an animation, not relevant)
Finally you can test it like this:
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
....
[self _teste];
}
-(void)_teste
{
Red __weak *mySelf = self;
dispatch_after_secs_on_main(0.5, ^
{
NSLog(@"tick !!!!!!!!!!!!");
if ( mySelf == nil ) NSLog(@"I no longer exist - WTF!");
[mySelf _teste];
});
}
You can see clearly that once the "Red" vc is dismissed, indeed, the ticker stops running: "Red" has gone away.
It does seem to work reliably. Your output will look something like this...
2014-10-22 17:26:36.498 [1738:111092] tick --- !!!!!!!!!!!!
2014-10-22 17:26:37.031 [1738:111092] tick --- !!!!!!!!!!!!
2014-10-22 17:26:37.576 [1738:111092] tick --- !!!!!!!!!!!!
2014-10-22 17:26:38.124 [1738:111092] tick --- !!!!!!!!!!!!
2014-10-22 17:26:38.674 [1738:111092] tick --- !!!!!!!!!!!!
2014-10-22 17:26:39.217 [1738:111092] tick --- !!!!!!!!!!!!
2014-10-22 17:26:39.764 [1738:111092] tick --- !!!!!!!!!!!!
2014-10-22 17:26:39.764 [1738:111092] I no longer exist --- WTF!
To reiterate, as AnujYadav points out, if you use a property in the parent VC for the "Red"...
@property (strong) Red *red;
then
self.red = (Red *)[self.storyboard
instantiateViewControllerWithIdentifier:@"RedID"];
etc ... indeed this DOES NOT work. In that case, you would have to self.red=nil in the parent, or it will not go away.
Upvotes: 13
Reputation: 990
There seems to be a difference in your question and answer. In your overlay method (in answer) you did not assigned the ViewController to any strong property and in question you have strong property. I have not tested the code but I feel you should update your test to have a strong property.
I think ideally we should "nil" the property. Otherwise, from stack yes view controller will be removed.
Upvotes: 2
Reputation: 2712
This is more memory management question than view controller containment one. No you don't need to put nil there, but...
You are assuming that you have a reference to it. Question is: is it strong reference? if yes, than you have to nil it, because that view controller will not be dellocated. Easiest way to test it is to add -dealoc method to rm with log message.
Upvotes: 3