seedante / iOS-ViewController-Transition-Demo

《iOS 视图控制器转场详解》配套 Demo
479 stars 129 forks source link

发现一个内存相关的问题 #3

Closed Xwnine closed 8 years ago

Xwnine commented 8 years ago

class OverlayAnimationController: NSobject, UIViewControllerAnimatedTransitioning{ ... func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
... //不像容器 VC 转场里需要额外的变量来标记操作类型,UIViewController 自身就有方法跟踪 Modal 状态。 //处理 Presentation 转场: if toVC.isBeingPresented(){ //1 containerView.addSubview(toView) //在 presentedView 后面添加暗背景视图 dimmingView,注意两者在 containerView 中的位置。 let dimmingView = UIView() containerView.insertSubview(dimmingView, belowSubview: toView)

        //设置 presentedView 和 暗背景视图 dimmingView 的初始位置和尺寸。
        let toViewWidth = containerView.frame.width * 2 / 3
        let toViewHeight = containerView.frame.height * 2 / 3
        toView.center = containerView.center
        toView.bounds = CGRect(x: 0, y: 0, width: 1, height: toViewHeight)

        dimmingView.backgroundColor = UIColor(white: 0.0, alpha: 0.5)
        dimmingView.center = containerView.center
        dimmingView.bounds = CGRect(x: 0, y: 0, width: toViewWidth, height: toViewHeight)

        //实现出现时的尺寸变化的动画:
        UIView.animateWithDuration(duration, delay: 0, options: .CurveEaseInOut, animations: {
            toView.bounds = CGRect(x: 0, y: 0, width: toViewWidth, height: toViewHeight)
            dimmingView.bounds = containerView.bounds
            }, completion: {_ in
                //2
                let isCancelled = transitionContext.transitionWasCancelled()
                transitionContext.completeTransition(!isCancelled)
        })
    }
    //处理 Dismissal 转场,按照上一小节的结论,.Custom 模式下不要将 toView 添加到 containerView,省去了上面标记1处的操作;
    if fromVC.isBeingDismissed(){
        let fromViewHeight = fromView.frame.height
        UIView.animateWithDuration(duration, animations: {
            fromView.bounds = CGRect(x: 0, y: 0, width: 1, height: fromViewHeight)
            }, completion: { _ in
                //2
                let isCancelled = transitionContext.transitionWasCancelled()
                transitionContext.completeTransition(!isCancelled)
        })
    }
}

}

不知楼主有没有测试过,在Modal转场实践中,这段代码会有一个小小的内存问题。多次present、dimiss切换,内存会一直以0.1M的增量上涨,不会回落,用Xcode的Leaks工具检测,并没有发现内存泄漏,我尝试着打印了containerView的subViews,发现并没有什么异常。我尝试着在这个OverlayAnimationController类中添加了一个 weak var maskView来替代原有的dimmingView,并且在dismiss中将fromView从containerView中移除,发现内存并没有回落。有些困惑,特来请教,谢谢了!

seedante commented 8 years ago

我试了下,没有发现内存泄露,而每次 dismiss 后都会调用 deinit,而我观察到有时 dismiss 后内存并没有立即回落,但是多次快速 present 然后 dismiss,内存会上升0.1M 然后回落,不会累积上升。我的测试环境是:iPad mini 1代,iOS 9.3.2,Xcode 7.3.2。

seedante commented 8 years ago

@qshuangwen ?