iOS Swift: UIViewControllerAnimatedTransitioning 结束帧位置错误

iOS Swift: UIViewControllerAnimatedTransitioning end frame in wrong position

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

调用转换时,单元格中的图像应该移动到目标 viewController 上 UIImageView 的最终位置。然而,它所做的是在过渡完成之前移动到屏幕的另一边,视图发生变化,使图像看起来像回到视图的中心。

我阅读了很多试图解决这个问题的教程,也阅读了很多 Whosebug,但都没有弄明白。有人可以向我指出我错过了什么吗?我要疯了,在这里。

调用转换的segue,原ViewController:

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
  }
}

这是来自 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)
  }

}

这很难说,但这是我的 猜测: 您使用的尺寸 类,设计尺寸 any/any,图像在当您将其框架用于动画时,您的视图控制器仍然居中,使其太靠右。转换完成后,将进行布局传递并进行更正。

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

toViewController.view.setNeedsLayout()
toViewController.view.layoutIfNeeded()

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