Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

custom iOS 7 UIViewController transition retain cycle

I'm creating custom transitions in my app and running into two problems. If I set the view controller to handle both UIViewControllerAnimatedTransitioning and UIViewControllerTransitioningDelegate I run into the problem of my view controller never being deallocated. Specifically, this creates the retain:

self.transitioningDelegate = self;

If I don't do that, and put UIViewControllerAnimatedTransitioning and UIViewControllerTransitioningDelegate in a separate NSObject called TransitionController and set it like this:

self.transitioningDelegate = [[TransitionController alloc] init];

the UIViewController is deallocated, but I get memory leaks on the TransitionController object. Does anyone now what I'm doing wrong?

like image 577
kelly Avatar asked Nov 12 '13 06:11

kelly


2 Answers

I ran into the same issue and was able to solve it.
The custom transition API is not that well documented and required a lot of trial and error for me to get everything right.

Let me walk you through how I was able to make it work nicely without any memory issues:

Here are the players:

VCA = The view controller that wants to present VCB modally
VCB = The modally presented view controller (presented by VCA)

TC = The custom transition controller object that performs the custom animation.
NSObject subclass that conforms to "UIViewControllerAnimatedTransitioning".
Will be instantiated within TD.

TD = The custom transition delegate object that provides the transition controller to the system. NSObject subclass that conforms to "UIViewControllerTransitioningDelegate"

Now let's present an instance of VCB

self = an instance of VCA
myModalViewController = is a strong property of self

self.myModalViewController = [[VCB alloc] init];

[self.myModalViewController setModalPresentationStyle: UIModalPresentationCustom];
[self.myModalViewController setTransitioningDelegate: [[TD alloc] init]];
[self presentViewController: self.myModalViewController
                   animated:YES 
                 completion:NULL];

At some point later, VCB asks VCA to be dismissed

self = an instance of VCA
myModalViewController = the modally presented instance of VCB presented earlier

[self dismissViewControllerAnimated:YES 
                         completion:^{
             [self.myModalViewController setTransitioningDelegate: nil]; // DO THIS!!!! 
             self.myModalViewController = nil;
        }];



I hope this helps. It certainly did for me.

like image 156
tiescher Avatar answered Oct 15 '22 05:10

tiescher


In my case I had self (UIViewController) holding an instance of a custom UIViewController (lets call it mViewController), and self is the transitioningDelegate of showing/dismissing mViewConroller. My solution to avoid retain-cycle was to call this inside the .m of mViewController:

-(void)viewDidDisappear:(BOOL)animated {
    self.transitioningDelegate = nil;
    [super viewDidDisappear:animated];
}

Worked like a charm (:

like image 40
Aviel Gross Avatar answered Oct 15 '22 04:10

Aviel Gross