View Controllers

UIViewController is one of the most-used APIs in iOS.

Lifecycle

A common interview question, if simple.

  • init
  • awakeFromNib (if available)
  • viewDidLoad
  • viewWillAppear
  • viewDidLayoutSubviews (And any subsequent times the view’s subviews are laid out)
  • viewDidAppear

Ending:

  • viewWillDisappear
  • viewDidDisappear
  • deinit/dealloc

Transitions

Adding custom transitions, specifically.

Theory

Example

Because these are all objective-c protocols, they need to be NSObject subclasses, so:

class PageCurlAnimatedTransitioning: NSObject, UIViewControllerAnimatedTransitioning {
	func transitionDuration(using context: UIViewControllerContextTransitioning?) -> TimeInteral {
	    return 0.25
	}
	
	func animateTransition(using context: UIViewControllerContextTransitioning) {
		guard let fromVC = context.viewController(forKey: .from),
			let toVC = context.viewController(forKey: .to),
			let snapshot = toVC.view.snapshotView(afterScreenUpdates: true) else {
				return
			}
		let containerView = context.containerView
		let startFrame = context.initialFrame(for: fromVC)
		let finalFrame = context.finalFrame(for: toVC)
		
		snapshot.frame = startFrame
		
		containerView.addSubview(toVC.view)
		containerView.addSubview(snapshot)
		toVC.view.isHidden = true
		
		UIView.animate(
			withDuration: self.transitionDuration(using: context),
			delay: 0,
			options: [.transitionCurlUp, .preferredFramesPerSecond60],
			animations: {
				snapshot.frame = finalFrame
		},
			completion: { _ in
				snapshot.removeFromSuperview()
				toVC.view.isHidden = false
		})
	}
}

class MyTransitioningDelegate: NSObject, UIViewControllerTransitioningDelegate {
    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    	return PageCurlAnimatedTransitioning()
    }
}

And these would be used like so:

self.transitioner = MyTransitioningDelegate() // hold a strong reference to this.
let viewControllerToPresent = // ...
viewControllerToPresent.modalPresentationStyle = .custom
viewControllerToPresent.transitioningDelegate = self.transitioner
vc.present(viewControllerToPresent, animated: true, completion: nil)

Last updated: 2020-06-07 16:24:37 -0700