рдПрдХ рджреГрд╢реНрдп рдирд┐рдпрдВрддреНрд░рдХ рдХреА рдХрд╣рд╛рдиреА рдЬреЛ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рджрд┐рдЦрд╛рдирд╛ рдЪрд╛рд╣рддреА рдереА

рдПрдХ рдмрд╛рд░ рдПрдХ рдорд╛рдореВрд▓реА рджреГрд╢реНрдп рдирд┐рдпрдВрддреНрд░рдХ VCYellow рдерд╛ ред рдФрд░ рдЙрд╕рдХреЗ рдкрд╛рд╕ рди рддреЛ рдХреЛрдИ рдЪрд┐рддреНрд░ рдерд╛, рди рдкрд╛рда, рди рд╣реА рдПрдХ рдЫреЛрдЯрд╛ рд╕рд╛ рд╡реНрдпрд╡рд╕рд╛рдпрд┐рдХ рддрд░реНрдХред рдЙрдиреНрд╣реЛрдВрдиреЗ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рджреГрд╢реНрдп-рдирд┐рдпрдВрддреНрд░рдХ рдЬреАрд╡рди рдЬреАрдпрд╛ред


рдЙрдирдХреЗ рд╕рд╛рдереА рджреГрд╢реНрдп рдирд┐рдпрдВрддреНрд░рдХ VCMain рдиреЗ рдХрднреА-рдХрднреА рдЗрд╕реЗ рджреБрдирд┐рдпрд╛ рдХреЗ рд╕рд╛рдордиреЗ рдкреЗрд╢ рдХрд┐рдпрд╛:


class VCMain: UIViewController { ... @IBAction func onBtnTapMeTapped(_ sender: Any) { let vcYellow = self.storyboard!.instantiateViewController(withIdentifier: "VCYellow") as! VCYellow self.present(vcYellow, animated: true, completion: nil) } 

рдФрд░ VCYellow, рдмрджрд▓реЗ рдореЗрдВ, рдПрдХ рдПрдХрд▓ "X" рдмрдЯрди рдХреА рдорджрдж рд╕реЗ рдЫрд┐рдкрд╛ рд░рд╣рд╛ рдерд╛, рдЬрд┐рд╕реЗ рд╡рд╣, рд╡реИрд╕реЗ, рдмрд╣реБрдд рдЧрд░реНрд╡ рдерд╛:


 class VCYellow: UIViewController { ... @IBAction func onBtnCloseTapped(_ sender: Any) { self.dismiss(animated: true, completion: nil) } 

рдФрд░ рдпрд╣ рдмрд╣реБрдд рдмреБрд░рд╛ рдирд╣реАрдВ рд▓рдЧ рд░рд╣рд╛ рдерд╛, рд▓реЗрдХрд┐рди рдЙрдмрд╛рдК рдФрд░ рд╕рд╛рдВрд╕рд╛рд░рд┐рдХ:



рд▓реЗрдХрд┐рди рд╣рдорд╛рд░реЗ рдирд╛рдпрдХ рдХрд╛ рд╕рдкрдирд╛ рдерд╛ рдХрд┐ рд╣рдо рд╕реБрдВрджрд░рддрд╛ рдХреЛ рджрд┐рдЦрд╛рдирд╛ рдФрд░ рдЫрд┐рдкрд╛рдирд╛ рд╕реАрдЦреЗрдВред рд╣рд╛рдВ, рддрд╛рдХрд┐ рдЖрдк рдЗрд╕ рд╕реБрдВрджрд░рддрд╛ рдХреЛ рдмрд╛рдж рдореЗрдВ рдЫреБрдЯреНрдЯрд┐рдпреЛрдВ рдкрд░ рдпрд╛ рд╕рд┐рд░реНрдл рдПрдХ рдЕрдЪреНрдЫреЗ рдореВрдб рдХреЗ рд╕рдореНрдорд╛рди рдореЗрдВ рдмрджрд▓ рд╕рдХреЗрдВред



рд╕рд╛рд▓ рдмреАрдд рдЧрдП ... рдФрд░ рдЗрд╕рд▓рд┐рдП рд╕рдкрдирд╛ рд╕рдкрдирд╛ рд╣реА рд░рд╣ рдЧрдпрд╛ рдХрд┐ рд╡реАрд╕реАрдпреЗрд▓реЛ рдХреЗ рд▓рд┐рдП рдЬрд╛рджреВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдиреЗ рдХрд╛ рдореМрдХрд╛ рдирд╣реАрдВ рдорд┐рд▓рд╛:


 UIViewControllerTransitioningDelegate 

рдФрд░ рдЗрд╕ рдЬрд╛рджреВ рдХреА рд╢рдХреНрддрд┐ рдЗрд╕ рддрдереНрдп рдореЗрдВ рдирд┐рд╣рд┐рдд рд╣реИ рдХрд┐ рдпрд╣ рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдФрд░ рджреГрд╢реНрдп рдирд┐рдпрдВрддреНрд░рдХ рдХреЛ рдЫрд┐рдкрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреБрдХреНрдд рдПрдирд┐рдореЗрдЯрд░ рдХреЛ рдкрд░реНрдЪреА рдХрд░рдирд╛ рд╕рдВрднрд╡ рдмрдирд╛рддрд╛ рд╣реИред рдмрд╕ рдХреНрдпрд╛ рд╣рдорд╛рд░реЗ рдирд┐рдпрдВрддреНрд░рдХ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕рдкрдирд╛ рджреЗрдЦрд╛ред
рдЙрдиреНрд╣реЛрдВрдиреЗ рдкреНрд░рд╛рдЪреАрди рд╕реНрдХреНрд░реЙрд▓ рдореЗрдВ рдкрдврд╝рд╛ рдХрд┐ рдордВрддреНрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд░реЗрдВ рдФрд░ рддреИрдпрд╛рд░ рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░реЗрдВред
рдореИрдВрдиреЗ рдЦреБрдж рдХреЛ рдордВрддреНрд░ рдХреЗ рд╕рд╛рде рдПрдХ рдкрд╛рд▓рдирд╛ рд▓рд┐рдЦрд╛ рдерд╛ рддрд╛рдХрд┐ рднреВрд▓ рди рдЬрд╛рдП:


 extension VCYellow: UIViewControllerTransitioningDelegate { func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { return AnimatorPresent(startFrame: self.startFrame) } func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { return AnimatorDismiss(endFrame: self.startFrame) } } 

рдЗрд╕рдореЗрдВ, рдЙрдиреНрд╣реЛрдВрдиреЗ рдзреНрдпрд╛рди рд╕реЗ рдЪрд┐рддреНрд░рд┐рдд рдХрд┐рдпрд╛ рдХрд┐ рд╢реЛ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рдПрдирд┐рдореЗрдЯрд░ рдПрдирд┐рдореЗрдЯрд░рдкреНрд░реЗрдВрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдФрд░ рдЬрдм рдПрдирд┐рдореЗрдЯрд░рдбрд┐рдЬреНрдо рдХреЛ рдмрдВрдж рдХрд░рдирд╛ рд╣реИред
рдЦреИрд░, рджреЛрдиреЛрдВ рдПрдирд┐рдореЗрдЯрд░реЛрдВ рдХреА рд╕рд╣рд╛рдпрддрд╛ рдХреЗ рд░реВрдк рдореЗрдВ, рдореБрдЦреНрдп рдмрдЯрди рдлреНрд░реЗрдо рдХреЛ рд╡реАрд╕реАрдореИрди рд╕реЗ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ рдЧрдпрд╛


рдФрд░ рдлрд┐рд░ рд╡рд╣ рдЦреБрдж рдорд╛рдирд╕рд┐рдХ рд░реВрдк рд╕реЗ рдХрдордЬреЛрд░ рд╣реЛ рдЧрдпрд╛ рдерд╛ред рдХреНрдпреЛрдВрдХрд┐ рд╕рд╣реА рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рдмрд┐рдирд╛, рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ, рдХреЛрдИ рдЬрд╛рджреВ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ:


 override func viewDidLoad() { super.viewDidLoad() self.modalPresentationStyle = .custom self.transitioningDelegate = self } 

рдЙрдиреНрд╣реЛрдВрдиреЗ рдЕрдкрдиреЗ рджреЛрд╕реНрдд рд╡реАрд╕реАрдореИрди рд╕реЗ рдХрд╣рд╛ рдХрд┐ рд╡рд╣ рдЬрд╛рджреВ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЦреБрдж рдХреЛ рдкреНрд░рд╕реНрддреБрдд рдХрд░реЗрдВ рдФрд░ рдпрд╣ рдХрд┐рд╕реА рднреА рддрд░рд╣ рд╕реЗ рдХрд╛рдо рди рдХрд░реЗ ...
рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рдХрд┐ рдПрдирд┐рдореЗрдЯрд░реЗрд╕реНрдкреНрд░реЗрд╕реЗрдВрдЯ рдФрд░ рдПрдирд┐рдореЗрдЯрд░рдбрд┐рдЬреНрдо рд╕реНрд╡рдпрдВ рдкреНрд░рдХрдЯ рдирд╣реАрдВ рд╣реЛрддреЗ рд╣реИрдВред


рдЗрд╕реЗ рд░реЛрдХрдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рджреЗрд░ рд╣реЛ рдЪреБрдХреА рдереА, рдФрд░ рд╣рдорд╛рд░реЗ рдирд╛рдпрдХ рдиреЗ рдЖрд╡рд╢реНрдпрдХ рдПрдирд┐рдореЗрдЯрд░реЛрдВ рдХреЛ рдмрдирд╛рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред рдореИрдВрдиреЗ рдкреНрд░рд╛рдЪреАрди рд╕реНрдХреНрд░реЙрд▓ рдХреЗ рдЖрд╡рд╢реНрдпрдХ рдЕрдиреБрднрд╛рдЧ рдореЗрдВ рдЪрд╛рд░реЛрдВ рдУрд░ рдкреЛрдХ рдХрд┐рдпрд╛ рдФрд░ рдкрд╛рдпрд╛ рдХрд┐ рдПрдХ рдПрдирд┐рдореЗрдЯрд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рджреЛ рдЪреАрдЬреЗрдВ рдкрд░реНрдпрд╛рдкреНрдд рд╣реИрдВред


рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЖрдкрдХреЛ рдПрдиреАрдореЗрд╢рди рдХреЗ рд▓рд┐рдП рдЖрд╡рдВрдЯрд┐рдд рд╕рдордп рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:


 func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return 0.3 } 

рдФрд░ рджреВрд╕рд░рд╛ рдПрдиреАрдореЗрд╢рди рдХреЛ рд╕реНрд╡рдпрдВ рдЗрдВрдЧрд┐рдд рдХрд░реЗрдВ:


 func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { //1 guard let vcTo = transitionContext.viewController(forKey: .to), let snapshot = vcTo.view.snapshotView(afterScreenUpdates: true) else { return } //2 let vContainer = transitionContext.containerView //3 vcTo.view.isHidden = true vContainer.addSubview(vcTo.view) //4 snapshot.frame = self.startFrame vContainer.addSubview(snapshot) UIView.animate(withDuration: 0.3, animations: { //5 snapshot.frame = (transitionContext.finalFrame(for: vcTo)) }, completion: { success in //6 vcTo.view.isHidden = false snapshot.removeFromSuperview() transitionContext.completeTransition(true) }) } 

  1. рдкреНрд░рд╕реНрддреБрдд рджреГрд╢реНрдп рдирд┐рдпрдВрддреНрд░рдХ (рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ VCYellow) рдХреЛ рдмрд╛рд╣рд░ рдирд┐рдХрд╛рд▓реЗрдВ рдФрд░ рдЗрд╕рдХреА рдПрдХ рддрд╕реНрд╡реАрд░ рд▓реЗрдВред рдПрдиреАрдореЗрд╢рди рдХреЛ рд╕рд░рд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рддрд╕реНрд╡реАрд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред
  2. рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ рдЬрд┐рд╕ рдкрд░ рдПрдирд┐рдореЗрдЯреЗрдб рдЬрд╛рджреВ рдЯреЛрдирд╛ рд╣реЛрдЧрд╛ред рдЗрд╕реЗ рд╕рдВрджрд░реНрдн рдХрд╣рддреЗ рд╣реИрдВред
  3. рд╕рдВрджрд░реНрдн рдкрд░ рдЕрдВрддрд┐рдо рдирд┐рдпрдВрддреНрд░рдХ рдХреЗ рджреГрд╢реНрдп рдХреЛ рд╣реБрдХ рдХрд░реЗрдВ рдФрд░ рдЗрд╕реЗ рдЫрд┐рдкрд╛рдПрдВред рдкреНрд░рджрд░реНрд╢рди
  4. рдпрд╣ рдПрдиреАрдореЗрд╢рди рд╕рдорд╛рдкреНрдд рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж рддрдп рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред
  5. рдПрдиреАрдореЗрд╢рди рдХреЗ рд▓рд┐рдП рдПрдХ рдлреЛрдЯреЛ рддреИрдпрд╛рд░ рдХрд░реЗрдВред рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдЖрдХрд╛рд░ рдХреЛ рдХрдо рдХрд░реЗрдВ рдФрд░ рд╕рдВрджрд░реНрдн рдкрд░ рдлреЗрдВрдХ рджреЗрдВред
  6. рдлрд╝реЛрдЯреЛ рдХреЛ рдкреВрд░реНрдг рд╕реНрдХреНрд░реАрди рдкрд░ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░реЗрдВ, рдЬрд┐рд╕рд╕реЗ рдкреНрд░рд╕реНрддреБрддрд┐ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдПрдирд┐рдореЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗред
  7. рдПрдиреАрдореЗрд╢рди рд╕рдорд╛рдкреНрдд рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж, рдЕрдВрддрд┐рдо рдирд┐рдпрдВрддреНрд░рдХ рдХрд╛ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рджреГрд╢реНрдп рджрд┐рдЦрд╛рдПрдВ,
  8. рдлреЛрдЯреЛ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдПрдВ рдФрд░ рд░рд┐рдкреЛрд░реНрдЯ рдХрд░реЗрдВ рдХрд┐ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдЦрддреНрдо рд╣реЛ рдЧрдИ рд╣реИред

рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рдкреНрд░рджрд░реНрд╢рди рдХреЗ рд▓рд┐рдП рдРрд╕рд╛ рдПрдХ рдПрдирд┐рдореЗрдЯрд░ рдерд╛:


 import UIKit class AnimatorPresent: NSObject, UIViewControllerAnimatedTransitioning { let startFrame: CGRect init(startFrame: CGRect) { self.startFrame = startFrame } func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return 0.3 } func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { guard let vcTo = transitionContext.viewController(forKey: .to), let snapshot = vcTo.view.snapshotView(afterScreenUpdates: true) else { return } let vContainer = transitionContext.containerView vcTo.view.isHidden = true vContainer.addSubview(vcTo.view) snapshot.frame = self.startFrame vContainer.addSubview(snapshot) UIView.animate(withDuration: 0.3, animations: { snapshot.frame = (transitionContext.finalFrame(for: vcTo)) }, completion: { success in vcTo.view.isHidden = false snapshot.removeFromSuperview() transitionContext.completeTransition(true) }) } } 

рдФрд░ рдЙрд╕рдХреЗ рдмрд╛рдж рдЫрд┐рдкрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдПрдирд┐рдореЗрдЯрд░ рд▓рд┐рдЦрдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рдерд╛, рдЬреЛ рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрдд:


 import UIKit class AnimatorDismiss: NSObject, UIViewControllerAnimatedTransitioning { let endFrame: CGRect init(endFrame: CGRect) { self.endFrame = endFrame } func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return 0.3 } func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { guard let vcTo = transitionContext.viewController(forKey: .to), let vcFrom = transitionContext.viewController(forKey: .from), let snapshot = vcFrom.view.snapshotView(afterScreenUpdates: true) else { return } let vContainer = transitionContext.containerView vContainer.addSubview(vcTo.view) vContainer.addSubview(snapshot) vcFrom.view.isHidden = true UIView.animate(withDuration: 0.3, animations: { snapshot.frame = self.endFrame }, completion: { success in transitionContext.completeTransition(true) }) } } 

рд╕рднреА рдкрд░рд┐рд╖реНрдХрд░рдг рд╕реНрдкрд░реНрд╢ рд╕рдорд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, VCYellow рдиреЗ рдлрд┐рд░ рд╕реЗ рдЕрдкрдиреЗ рдорд┐рддреНрд░ VCMain рдХреЛ рдЦреБрдж рдХреЛ рдФрд░ рд▓реЛ рдкреЗрд╢ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣рд╛!



рдЬрд╛рджреВ рдХрд╛рдо рдХрд░ рдЧрдпрд╛! VCYellow рдХрд╛ рд╕рдкрдирд╛ рд╕рдЪ рд╣реЛ рдЧрдпрд╛! рдЕрдм рд╡рд╣ рдЬреИрд╕рд╛ рдЪрд╛рд╣реЗ рд╡реИрд╕рд╛ рджрд┐рдЦрд╛ рдФрд░ рдЫрд┐рдкрд╛ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдХреБрдЫ рднреА рдЙрд╕рдХреА рдХрд▓реНрдкрдирд╛ рдХреЛ рд╕реАрдорд┐рдд рдирд╣реАрдВ рдХрд░реЗрдЧрд╛!


рдПрдХ рдЙрджрд╛рд╣рд░рдг рдкрд░рд┐рдпреЛрдЬрдирд╛ рдпрд╣рд╛рдВ рдбрд╛рдЙрдирд▓реЛрдб рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИред


рдкреНрд░реЗрд░рдгрд╛ рдХреЗ рд▓рд┐рдП рдореИрдВрдиреЗ рдЬреЛ рд▓реЗрдЦ рдкреНрд░рдпреЛрдЧ рдХрд┐рдпрд╛, рд╡рд╣ рдпрд╣рд╛рдБ рд╣реИред

Source: https://habr.com/ru/post/hi424853/


All Articles