ClaytonAV
ClaytonAV

Reputation: 95

Swift - Navigation Controller no Killing View Controller Instance

I am using a custom Navigation Controller to show and hide two ViewControllers. The code that will call the ViewController to show some movie detail is:

func tapGestureRecognizer(gestureRecognizer: UITapGestureRecognizer){
        self.searchBarTop.endEditing(true)
        let p = gestureRecognizer.locationInView(self.collectionViewMovies)
        let tag = gestureRecognizer.view?.tag
        if tag == 1{
            if let indexPath : NSIndexPath = (self.collectionViewMovies?.indexPathForItemAtPoint(p)){
                if let cell = self.collectionViewMovies.cellForItemAtIndexPath(indexPath){
                    cellAnimation.imageBlurCell(cell, style: .Light, alpha: 1.0, completion: { (complete) -> Void in
                        if let record = self.fetchedResultsController.objectAtIndexPath(indexPath) as? Movies{
                            let movieId = record.movieid as! Int
                            NSNotificationCenter.defaultCenter().postNotificationName("moviesShouldGetDetails", object: nil, userInfo: ["movieId":movieId])
                            let destination = self.myStoryboard.instantiateViewControllerWithIdentifier("MovieDetails") as! MovieDetailsViewController
                            destination.movieId = movieId
                            self.navigationController?.pushViewController(destination, animated: true)
                        }
                    })
                }
            }
        }
    }

I am creating a new instance of MovieDetailsViewController every time. The problem is that i thought that after the NavigationController Pop the ViewController the instance would be killed, but this is not happing. I have some Observers inside the MovieDetailsViewController and i can see that the instance still running. The NavigationController delegate is:

func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        if operation == .Push {
            customInteractionController.attachToViewController(toVC)
        }
        customNavigationAnimationController.reverse = operation == .Pop
        return customNavigationAnimationController
    }

    func navigationController(navigationController: UINavigationController, interactionControllerForAnimationController animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
        return customInteractionController.transitionInProgress ? customInteractionController : nil
    }

The code to control the animation is bellow, i tried to force the Navigation Pop again, when the animation complete, but no luck so far.

import UIKit

class CustomNavigationAnimationController: NSObject, UIViewControllerAnimatedTransitioning {

    var reverse = false

    func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
        return 0.5
    }

    func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
        let containerView = transitionContext.containerView()
        let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!
        let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!
        let toView = toViewController.view
        let fromView = fromViewController.view
        let direction: CGFloat = reverse ? -1 : 1
        let const: CGFloat = -0.005

        toView.layer.anchorPoint = CGPointMake(direction == 1 ? 0 : 1, 0.5)
        fromView.layer.anchorPoint = CGPointMake(direction == 1 ? 1 : 0, 0.5)

        var viewFromTransform: CATransform3D = CATransform3DMakeRotation(direction * CGFloat(M_PI_2), 0.0, 1.0, 0.0)
        var viewToTransform: CATransform3D = CATransform3DMakeRotation(-direction * CGFloat(M_PI_2), 0.0, 1.0, 0.0)
        viewFromTransform.m34 = const
        viewToTransform.m34 = const

        containerView!.transform = CGAffineTransformMakeTranslation(direction * containerView!.frame.size.width / 2.0, 0)
        toView.layer.transform = viewToTransform
        containerView!.addSubview(toView)

        UIView.animateWithDuration(transitionDuration(transitionContext), animations: {
            containerView!.transform = CGAffineTransformMakeTranslation(-direction * containerView!.frame.size.width / 2.0, 0)
            fromView.layer.transform = viewFromTransform
            toView.layer.transform = CATransform3DIdentity
            }, completion: {
                finished in
                containerView!.transform = CGAffineTransformIdentity
                fromView.layer.transform = CATransform3DIdentity
                toView.layer.transform = CATransform3DIdentity
                fromView.layer.anchorPoint = CGPointMake(0.5, 0.5)
                toView.layer.anchorPoint = CGPointMake(0.5, 0.5)

                if (transitionContext.transitionWasCancelled()) {
                    toView.removeFromSuperview()
                } else {
                    fromView.removeFromSuperview()
                    if self.reverse{
                        print("removing from superview")
                        fromViewController.navigationController?.popViewControllerAnimated(false)
                    }
                }
                transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
        })
    }
}

What am i missing here ? How can i kill my MovieDetailsViewController instance ? The NavigationController .Pop should not kill the instance form me ? Thanks in advance.

Upvotes: 0

Views: 1008

Answers (2)

ClaytonAV
ClaytonAV

Reputation: 95

After spend sometime understanding how ARC works i was able to fix the problem. I had some Strong Reference Cycles because of some delegates that was not declared like "weak". The other problem was in this line

customInteractionController.attachToViewController(toVC)

This code will create a Strong Reference with a NavigationViewController in another class, i just change this reference to weak. Now everything is working fine.

Upvotes: 0

William Rosenbloom
William Rosenbloom

Reputation: 2636

You say

I have some Observers inside the MovieDetailsViewController and i can see that the instance still running.

Could that possibly mean that you are retaining references to the MovieDetailsViewController after the pop? Swift's garbage collector will not deallocate the view controller until it no longer has any references. If you maintain references to the view controller it will stay alive even when off screen.

Upvotes: 0

Related Questions