我有一个名为ProfileCollectionViewController的集合视图,用于收集图像。 单击图像时,它会显示一个HorizontalProfileViewController,它以全屏显示图像。 当在HorizontalProfileViewController上按下后退按钮时,我希望全屏图像动画回到ProfileViewController中的缩略图。我将选中的索引路径从ProfileViewController作为initialIndexPath传递给HorizontalProfileViewController,以便知道缩略图的位置。下面是我的过渡动画代码
import UIKit
class SEHorizontalFeedToProfile: NSObject, UIViewControllerAnimatedTransitioning {
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return 0.2
}
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
if let profileVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) as? SEProfileGridViewController, horizontalFeedVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) as? SEProfileHorizontalViewController, containerView = transitionContext.containerView() {
let duration = transitionDuration(transitionContext)
profileVC.collectionView?.reloadData()
if let indexPath = horizontalFeedVC.initialIndexPath {
let cell = profileVC.collectionView?.cellForItemAtIndexPath(indexPath)
print(indexPath)
let imageSnapshot = horizontalFeedVC.view.snapshotViewAfterScreenUpdates(false)
let snapshotFrame = containerView.convertRect(horizontalFeedVC.view.frame, fromView: horizontalFeedVC.view)
imageSnapshot.frame = snapshotFrame
horizontalFeedVC.view.hidden = true
profileVC.view.frame = transitionContext.finalFrameForViewController(profileVC)
containerView.insertSubview(profileVC.view, belowSubview: horizontalFeedVC.view)
containerView.addSubview(imageSnapshot)
UIView.animateWithDuration(duration, animations: {
var cellFrame = CGRectMake(0, 0, 0, 0)
if let theFrame = cell?.frame {
cellFrame = theFrame
}
let frame = containerView.convertRect(cellFrame, fromView: profileVC.collectionView)
imageSnapshot.frame = frame
}, completion: { (succeed) in
if succeed {
horizontalFeedVC.view.hidden = false
// cell.contentView.hidden = false
imageSnapshot.removeFromSuperview()
transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
}
})
}
}
}
}
我放了断点并在代码中找到了
let cell = profileVC.collectionView?.cellForItemAtIndexPath(indexPath)
细胞是零。我不明白为什么会这样。请帮我。我提前谢谢你。
profileVC是UICollectionViewController的子类
PS:请查看以下完全相同的项目,没有任何问题。我试图模仿它,但它并不适用于我的。 https://github.com/PeteC/InteractiveViewControllerTransitions
答案 0 :(得分:0)
正如在该问题的评论中指出的那样,单元格设置为nil,因为单元格不可见。由于您的HorizontalProfileViewController允许滚动到其他图片,因此可以滚动到尚未在ProfileCollectionViewController中为其创建UICollectionViewCell的图像。
您可以通过滚动到UICollectionView上当前图像的位置来解决此问题。您说initialIndexPath
最初是首次选择的图像的indexPath。假设您在用户滚动到不同的图像时更新它,以便它仍然准确地表示屏幕上图像的indexPath,我们可以使用它来强制UICollectionView在必要时滚动到当前单元格。
通过对代码进行一些调整,这可以为您提供所需的效果:
import UIKit
class SEHorizontalFeedToProfile: NSObject, UIViewControllerAnimatedTransitioning {
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return 0.2
}
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
if let profileVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) as? SEProfileGridViewController, horizontalFeedVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) as? SEProfileHorizontalViewController, containerView = transitionContext.containerView() {
let duration = transitionDuration(transitionContext)
//profileVC.collectionView?.reloadData() //Remove this
if let indexPath = horizontalFeedVC.initialIndexPath {
var cell = profileVC.collectionView?.cellForItemAtIndexPath(indexPath) //make cell a var so it can be reassigned if necessary
print(indexPath)
if cell == nil{ //This if block is added. Again it is crucial that initialIndexPath was updated as the user scrolled.
profileVC.collectionView?.scrollToItemAtIndexPath(horizontalFeedVC.initialIndexPath, atScrollPosition: UICollectionViewScrollPosition.CenteredVertically, animated: false)
profileVC.collectionView?.layoutIfNeeded() //This is necessary to force the collectionView to layout any necessary new cells after scrolling
cell = profileVC.collectionView?.cellForItemAtIndexPath(indexPath)
}
let imageSnapshot = horizontalFeedVC.view.snapshotViewAfterScreenUpdates(false)
let snapshotFrame = containerView.convertRect(horizontalFeedVC.view.frame, fromView: horizontalFeedVC.view)
imageSnapshot.frame = snapshotFrame
horizontalFeedVC.view.hidden = true
profileVC.view.frame = transitionContext.finalFrameForViewController(profileVC)
containerView.insertSubview(profileVC.view, belowSubview: horizontalFeedVC.view)
containerView.addSubview(imageSnapshot)
UIView.animateWithDuration(duration, animations: {
var cellFrame = CGRectMake(0, 0, 0, 0)
if let theFrame = cell?.frame {
cellFrame = theFrame
}
let frame = containerView.convertRect(cellFrame, fromView: profileVC.collectionView)
imageSnapshot.frame = frame
}, completion: { (succeed) in
if succeed {
horizontalFeedVC.view.hidden = false
// cell.contentView.hidden = false
imageSnapshot.removeFromSuperview()
transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
}
})
}
}
}
现在,如果尚未创建当前的UICollectionViewCell:
滚动,以便单元格的indexPath以视图为中心
强制UICollectionView布局其子视图,从而创建必要的UITableViewCell
再次询问UITableViewCell,但这次不应该是nil