Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios UICollectionViewController的自定义pop动画不';行不通_Ios_Swift_Uicollectionview_Uianimation_Custom Transition - Fatal编程技术网

Ios UICollectionViewController的自定义pop动画不';行不通

Ios UICollectionViewController的自定义pop动画不';行不通,ios,swift,uicollectionview,uianimation,custom-transition,Ios,Swift,Uicollectionview,Uianimation,Custom Transition,我有一个名为ProfileCollectionViewController的收集视图,用于收集图像。 单击图像时,它会显示一个HorizontalProfileViewController,全屏显示图像。 当在水平ProfileViewController上按下“后退”按钮时,我希望全屏图像在ProfileViewController中动画化为缩略图。我将所选索引路径作为initialIndexPath从ProfileViewController传递到HorizontalProfileViewC

我有一个名为ProfileCollectionViewController的收集视图,用于收集图像。 单击图像时,它会显示一个HorizontalProfileViewController,全屏显示图像。 当在水平ProfileViewController上按下“后退”按钮时,我希望全屏图像在ProfileViewController中动画化为缩略图。我将所选索引路径作为initialIndexPath从ProfileViewController传递到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:请检查下面的项目,做完全相同的事情没有任何问题。我试着模仿它,但对我的不起作用。

正如在对问题的评论中所指出的,由于单元格不可见,因此将单元格设置为零。由于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尚未创建,请执行以下操作:

  • 滚动,使单元格的索引以视图为中心

  • 强制UICollectionView布局其子视图,从而创建任何必要的UITableViewCell

  • 再次请求UITableViewCell,但这次不应为零


  • 正如在对该问题的评论中所指出的,由于单元格不可见,因此将该单元格设置为零。由于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尚未创建,请执行以下操作:

  • 滚动,使单元格的索引以视图为中心

  • 强制UICollectionView布局其子视图,从而创建任何必要的UITableViewCell

  • 再次请求UITableViewCell,但这次不应为零


  • cellForItemAtIndexPath
    如果单元格不可见或indexPath超出范围,则返回nil。你的问题是为什么我的单元格不可见?我的问题是为什么toViewController的单元格在pop动画中为零?如何修复?在重新加载集合视图之前,您可能需要调整profileVC.view的大小并将其添加到容器中。该单元格不可见,因此
    cellForItemAtIndexPath
    将返回nil:。一种解决方案是传递集合视图单元格的框架,而不是索引路径。如果您需要一些代码,我有一个工作示例项目,但它非常简单。这对我不起作用,因为在全屏图像视图中,用户可以左右滑动以查看其他图像。initialIndexPath会相应地更新。
    cellForItemAtIndexPath
    如果单元格不可见或indexPath超出范围,则返回nil。你的问题是为什么我的单元格不可见?我的问题是为什么toViewController的单元格在pop动画中为零?如何修复?在重新加载集合视图之前,您可能需要调整profileVC.view的大小并将其添加到容器中。该单元格不可见,因此
    cellForItemAtIndexPath
    将返回nil:。一种解决方案是传递集合视图单元格的框架,而不是索引路径。如果您需要一些代码,我有一个工作示例项目,但它非常简单。这对我不起作用,因为在全屏图像视图中,用户可以左右滑动以查看其他图像。initialIndexPath将相应地更新。