I have been trying to make my custom transition while presenting another view controller and I succeeded in two ways. One is through using CGAfflineTransformIdentity and another just by pushing the ViewController using CGAffineTransformMakeTranslation.
The Apple documentation describes CGAfflineTransformIdentity as a unit identity matrix. How does my animation happen while I transform my view with identity matrix?
In real math while I multiply some thing with unit matrix I get the same matrix as a result.
So how does the transition really happen with CGAfflineTransformIdentity?
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
let container = transitionContext.containerView()
let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey)!
let toView = transitionContext.viewForKey(UITransitionContextToViewKey)!
let offScreenUp = CGAffineTransformMakeTranslation(0, -container.frame.size.height )
let offScreenDown = CGAffineTransformMakeTranslation(0, 0)
toView.transform = offScreenUp
container.addSubview(fromView)
container.addSubview(toView)
let duration = self.transitionDuration(transitionContext)
UIView.animateWithDuration(duration, delay: 0.0, usingSpringWithDamping: 1.0, initialSpringVelocity: 0.8, options: nil, animations: {
toView.transform = CGAffineTransformIdentity
//toView.transform = offScreenDown
}, completion: { finished in
// tell our transitionContext object that we've finished animating
transitionContext.completeTransition(true)
})
}
How does my animation happen while I transform my view with identity matrix
The answer to that is that technically, transforming a view with the identity matrix does nothing. However, setting the transform of your view to the identity matrix would undo any existing transform on that view. So if it had been scaled or rotated you would effectively undo that transition. In your case this means that you are undoing the translation transform that moved your view up so now it settles back to the origin.
This explains why in your animation block you can call either toView.transform = CGAffineTransformIdentity
OR toView.transform = offScreenDown
. CGAffineTransformMakeTranslation(0, 0)
is just the identity transform translated by zero points.
To prove that the identity transform is only undoing the initial transform you could concatenate it to your destination transform:
toView.transform = CGAffineTransformConcat(offScreenDown,CGAffineTransformIdentity)
As expected this has no effect since the identity transform only copies the contents of the transforms in a calculation:
The identity transform is a data transformation that copies the source data into the destination data without change (Wikipedia)
Meaning that inside your animation block offScreenDown
== CGAffineTransformIdentity
== CGAffineTransformConcat(offScreenDown,CGAffineTransformIdentity)
== CGAffineTransformConcat(CGAffineTransformIdentity,CGAffineTransformIdentity)
On iOS 7 its important to be mindful of identity transform as it pertains to animated transitions since I have found the container view applies a transform to its subviews to make sure they are in the correct orientation (since the container is actually inside a new UIWindow instance). This was actually mentioned in the Developer forums:
"For custom presentation transitions we setup an intermediate view between the window and the windows rootViewController's view. This view is the containerView that you perform your animation within. Due to an implementation detail of auto-rotation on iOS, when the interface rotates we apply an affine transform to the windows rootViewController's view and modify its bounds accordingly. Because the containerView inherits its dimensions from the window instead of the root view controller's view, it is always in the portrait orientation."