iOS Swift:UIViewControllerAnimatedTransitioning结束帧位置错误

Nat*_*olz 4 uiviewcontroller uiviewanimation ios swift

我有一个Swift项目,学习天气API,并试图更好地处理AnimatedTransitions.我有一个UITableView使用UITableViewCell图像和文字的自定义.点击tableView中的单元格转换为新UIViewController的Show(推送),整个内容嵌入到UINavigationController.

当调用转换时,来自单元的图像应该移动到UIImageView目标viewController上的最终位置.但是,它的作用是在转换完成并且视图发生变化之前移过该点到屏幕的远端,使图像看起来快照回到视图的中心.

截图

我已经阅读了很多教程试图解决这个问题,并且已经阅读了很多StackOverflow,但未能弄明白.有人可以向我指出我错过了什么吗?我疯了,在这里.

在原始ViewController中调用转换的segue:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
  self.performSegueWithIdentifier("SHOW_DETAIL", sender: self)
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
  if segue.identifier == "SHOW_DETAIL" {
    let detailVC = segue.destinationViewController as DetailViewController
    let indexPathForForecast = self.tableView.indexPathForSelectedRow() as NSIndexPath!
    let detailForecast = self.forecasts?[indexPathForForecast.row]
    let cell = self.tableView.cellForRowAtIndexPath(indexPathForForecast) as WeatherCell
    let image = cell.forecastImage.image
    detailVC.forecastForDetail = detailForecast
    detailVC.forecastDetailImage = image
  }
}

func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
  if fromVC == self && toVC.isKindOfClass(DetailViewController) {
    let transitionVC = AnimateToDetailVCController()
    return transitionVC
  } else {
    return nil
  }
}
Run Code Online (Sandbox Code Playgroud)

这是来自UIViewControllerAnimatedTransitioning对象的animateTransition代码(编辑:解码代码编辑成代码块,感谢@jrturton!)

func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
  let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) as ViewController
  let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) as DetailViewController

  let containerView = transitionContext.containerView()
  let duration = self.transitionDuration(transitionContext)

  let selectedRow = fromViewController.tableView.indexPathForSelectedRow()
  let cell = fromViewController.tableView.cellForRowAtIndexPath(selectedRow!) as WeatherCell
  let weatherSnapshot = cell.forecastImage.snapshotViewAfterScreenUpdates(false)
  weatherSnapshot.frame = containerView.convertRect(cell.forecastImage.frame, fromView: fromViewController.tableView.cellForRowAtIndexPath(selectedRow!)?.superview)
  cell.forecastImage.hidden = true

  toViewController.view.frame = transitionContext.finalFrameForViewController(toViewController)
  toViewController.view.alpha = 0
  toViewController.detailImageView.hidden = true

  containerView.addSubview(toViewController.view)
  containerView.addSubview(weatherSnapshot)

  var toFrame = toViewController.locationIs

  UIView.animateWithDuration(duration, animations: { () -> Void in
    // EDIT: This solved the issue, thanks JRTurton!
    toViewController.view.setNeedsLayout() // Solution: This is where it was needed
    toViewController.view.layoutIfNeeded() //  Solution: This is where it was needed

    toViewController.view.alpha = 1.0
    var endRect = containerView.convertRect(toViewController.detailImageView.frame, fromView: toViewController.view)
    weatherSnapshot.frame = endRect

  }) { (finished) -> Void in
    toViewController.detailImageView.hidden = false
    cell.forecastImage.hidden = false
    weatherSnapshot.removeFromSuperview()

    transitionContext.completeTransition(true)
  }

}
Run Code Online (Sandbox Code Playgroud)

jrt*_*ton 17

很难说,但这是我的猜测:你正在使用大小类,以任意/任何大小进行设计,当你将它的帧用于你的动画时,你的视图控制器中的图像仍然是中心的,使它太远了.转换完成后,将发生布局传递并进行更正.

要修复,在设置视图控制器的框架后,强制布局传递:

toViewController.view.setNeedsLayout()
toViewController.view.layoutIfNeeded()
Run Code Online (Sandbox Code Playgroud)

在进行上述更改之前,您可以通过在动画之前检查图像视图的帧来确认这是否是问题.