0

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.

2 Answers 2

0

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.

Sign up to request clarification or add additional context in comments.

5 Comments

the only reference to the MovieDetailsViewController is in a NSNotification NSNotificationCenter.defaultCenter().addObserver(self, selector: "movieDetailDidUpdate:", name: "movieDetailDidUpdate", object: nil) , i run it when the view did load. Can a observer prevent a ViewController to be deallocate ? I have to remove the observer ?
@ClaytonAV From the NSNotificationCenter docs "Be sure to invoke removeObserver:name:object: before notificationObserver or any object specified in addObserver:selector:name:object: is deallocated."
We always have to pay a price when we don´t learn something right, i will read the docs right now. Thank you very much to point me in the right direction. Later i will remove the observer and use a Delegate to see if will fix my problem.
Rosembloom . It´s working now and the problem was in the Observers and 1 delegate that i forgot to declare like weak.
Seems that i am wrong. The MovieDetailsViewController is deallocate, but the ViewController where i call the MovieDetailsViewController still there. The problem only happens if i use the custom NavigationController.
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.