Swift - 导航控制器没有杀死视图控制器实例
Posted
技术标签:
【中文标题】Swift - 导航控制器没有杀死视图控制器实例【英文标题】:Swift - Navigation Controller no Killing View Controller Instance 【发布时间】:2016-02-25 11:13:57 【问题描述】:我正在使用自定义导航控制器来显示和隐藏两个 ViewController。调用 ViewController 来显示电影细节的代码是:
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)
)
我每次都在创建一个新的 MovieDetailsViewController 实例。 问题是我认为在 NavigationController Pop ViewController 之后实例会被杀死,但这并没有发生。我在 MovieDetailsViewController 中有一些观察者,我可以看到该实例仍在运行。 NavigationController 委托是:
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
控制动画的代码如下,我尝试再次强制导航弹出,当动画完成时,但到目前为止没有运气。
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())
)
我在这里缺少什么?我怎样才能杀死我的 MovieDetailsViewController 实例? NavigationController .Pop 不应该杀死我的实例吗?提前致谢。
【问题讨论】:
【参考方案1】:你说
我在 MovieDetailsViewController 中有一些观察者,我可以看到实例仍在运行。
这可能意味着您在弹出后保留了对 MovieDetailsViewController 的引用吗? Swift 的垃圾收集器不会释放视图控制器,直到它不再有任何引用。如果您保持对视图控制器的引用,即使在屏幕外,它也会保持活动状态。
【讨论】:
MovieDetailsViewController 的唯一引用是在 NSNotification NSNotificationCenter.defaultCenter().addObserver(self, selector: "movieDetailDidUpdate:", name: "movieDetailDidUpdate", object: nil) 中,我运行它时视图确实加载了。观察者可以阻止 ViewController 被释放吗?我必须删除观察者? @ClaytonAV 来自NSNotificationCenter docs "确保在notificationObserver 或addObserver:selector:name:object:
中指定的任何对象被释放之前调用removeObserver:name:object:
。"
当我们学的东西不正确时,我们总是要付出代价,我现在就去读文档。非常感谢您为我指明正确的方向。稍后我将删除观察者并使用代表来查看是否可以解决我的问题。
玫瑰花。它现在可以工作了,问题出在观察者和我忘记声明为弱的 1 个代表中。
看来我错了。 MovieDetailsViewController 已解除分配,但我调用 MovieDetailsViewController 的 ViewController 仍然存在。只有当我使用自定义 NavigationController 时才会出现问题。【参考方案2】:
花了一些时间了解 ARC 的工作原理后,我能够解决问题。由于一些未声明为“弱”的代表,我有一些强参考周期。另一个问题在这一行
customInteractionController.attachToViewController(toVC)
这段代码将在另一个类中创建一个带有 NavigationViewController 的强引用,我只是将此引用更改为弱引用。现在一切正常。
【讨论】:
以上是关于Swift - 导航控制器没有杀死视图控制器实例的主要内容,如果未能解决你的问题,请参考以下文章