IOS рдкрд░ рд╕рд░реНрд╡рд╡реНрдпрд╛рдкреА рд╕реНрдкреНрд▓реИрд╢ рд╕реНрдХреНрд░реАрди рдмрдирд╛рдирд╛



рд╣рд╛рдп рд╣рдорд░!

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

рдмрдбрд╝реА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдХрдИ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЗ рд▓рд┐рдП, рд╕реБрдВрджрд░ рдПрдирд┐рдореЗрд╢рди рдмрдирд╛рдиреЗ рд╕реЗ рдЬреБрдбрд╝реА рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░рдирд╛ рдХреАрдбрд╝реЗ, рдЬрдЯрд┐рд▓ рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдФрд░ рдЧрд░реНрдо рдлрд┐рдХреНрд╕ рдХреА рджреБрдирд┐рдпрд╛ рдореЗрдВ рддрд╛рдЬреА рд╣рд╡рд╛ рдХреА рд╕рд╛рдВрд╕ рдмрди рдЬрд╛рддрд╛ рд╣реИред рдРрд╕реЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдЕрдкреЗрдХреНрд╖рд╛рдХреГрдд рдЖрд╕рд╛рди рд╣реИ, рдФрд░ рдкрд░рд┐рдгрд╛рдо рдЖрдВрдЦ рдХреЛ рднрд╛рддрд╛ рд╣реИ рдФрд░ рдмрд╣реБрдд рдкреНрд░рднрд╛рд╡рд╢рд╛рд▓реА рджрд┐рдЦрддрд╛ рд╣реИ! рд▓реЗрдХрд┐рди рдРрд╕реЗ рд╕рдордп рд╣реЛрддреЗ рд╣реИрдВ рдЬрдм рдорд╛рдирдХ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд▓рд╛рдЧреВ рдирд╣реАрдВ рд╣реЛрддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рдЖрдкрдХреЛ рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреЗ рд╡рд░реНрдХрдЖрд░реНрд╕ рдХреЗ рд╕рд╛рде рдЖрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред

рдкрд╣рд▓реА рдирдЬрд╝рд░ рдореЗрдВ, рд╕реНрдкреНрд▓реИрд╢ рд╕реНрдХреНрд░реАрди рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреЗ рдХрд╛рд░реНрдп рдореЗрдВ, рдПрдиреАрдореЗрд╢рди рдХрд╛ рдирд┐рд░реНрдорд╛рдг рд╕рдмрд╕реЗ рдХрдард┐рди рдкреНрд░рддреАрдд рд╣реЛрддрд╛ рд╣реИ, рдФрд░ рдмрд╛рдХреА рд╕рдм "рдирд┐рдпрдорд┐рдд рджрд┐рдирдЪрд░реНрдпрд╛" рд╣реИред рдХреНрд▓рд╛рд╕рд┐рдХ рд╕реНрдерд┐рддрд┐: рдкрд╣рд▓реЗ рд╣рдо рдПрдХ рд╕реНрдХреНрд░реАрди рджрд┐рдЦрд╛рддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рдПрдХ рдХрд╕реНрдЯрдо рд╕рдВрдХреНрд░рдордг рдХреЗ рд╕рд╛рде рд╣рдо рдЕрдЧрд▓реЗ рдПрдХ рдХреЛ рдЦреЛрд▓рддреЗ рд╣реИрдВ - рд╕рдм рдХреБрдЫ рд╕рд░рд▓ рд╣реИ!

рдПрдиреАрдореЗрд╢рди рдХреЗ рднрд╛рдЧ рдХреЗ рд░реВрдк рдореЗрдВ, рдЖрдкрдХреЛ рд╕реНрдкреНрд▓реИрд╢ рд╕реНрдХреНрд░реАрди рдкрд░ рдПрдХ рдЫреЗрдж рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдЕрдЧрд▓реА рд╕реНрдХреНрд░реАрди рдХреА рд╕рд╛рдордЧреНрд░реА рдкреНрд░рджрд░реНрд╢рд┐рдд рд╣реЛрддреА рд╣реИ, рдЕрд░реНрдерд╛рдд, рд╣рдореЗрдВ рдпрд╣ рдЬрд╛рдирдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рд╕реНрдкреНрд▓реИрд╢ рдХреЗ рдиреАрдЪреЗ рдХреМрди рд╕рд╛ view рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдпреБрд▓рд╛ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдЯреЗрдк рдЦреБрд▓рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╕рдВрдмрдВрдзрд┐рдд рдирд┐рдпрдВрддреНрд░рдХ рдХреЗ view рд╕рдВрд▓рдЧреНрди рдХрд░рдирд╛ рддрд░реНрдХрд╕рдВрдЧрдд рд╣реЛрдЧрд╛ред

рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдЕрдЧрд░ рдЖрдк рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдПрдХ рдкреБрд╢ рдЕрдзрд┐рд╕реВрдЪрдирд╛ рдХреЗ рд╕рд╛рде рдЪрд▓рд╛рддреЗ рд╣реИрдВ рдЬреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдХреА рдУрд░ рдЬрд╛рддрд╛ рд╣реИ? рдпрд╛ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рд╕реЗ рдЙрддреНрдкрд╛рдж рдХрд╛рд░реНрдб рдЦреЛрд▓реЗрдВ? рдлрд┐рд░ рдЕрдЧрд▓реА рд╕реНрдХреНрд░реАрди рдореЗрдВ рдмрд┐рд▓реНрдХреБрд▓ рднреА рдЯреЗрдк рдирд╣реАрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП (рдпрд╣ рд╕рднреА рд╕рдВрднрд╛рд╡рд┐рдд рдорд╛рдорд▓реЛрдВ рд╕реЗ рдмрд╣реБрдд рджреВрд░ рд╣реИ)ред рдФрд░ рдпрджреНрдпрдкрд┐ рд╕рднреА рд╕рдВрдХреНрд░рдордг рдореБрдЦреНрдп рд╕реНрдХреНрд░реАрди рдЦреЛрд▓рдиреЗ рдХреЗ рдмрд╛рдж рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ, рдПрдиреАрдореЗрд╢рди рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ view рд╕реЗ рдмрдВрдзрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХреМрди рд╕рд╛ рдирд┐рдпрдВрддреНрд░рдХ рд╣реИ?

рдкреНрд░рддреНрдпреЗрдХ рд╕реНрдерд┐рддрд┐ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдИ if-else рдмреНрд▓реЙрдХ рдХреА рдмреИрд╕рд╛рдЦреА рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП, рд╕реНрдкреНрд▓реИрд╢ рд╕реНрдХреНрд░реАрди рдХреЛ UIWindow рд╕реНрддрд░ рдкрд░ рджрд┐рдЦрд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рд▓рд╛рдн рдпрд╣ рд╣реИ рдХрд┐ рд╣рдо рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдкрд░рд╡рд╛рд╣ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдЫрдк рдХреЗ рдиреАрдЪреЗ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИ: рдЖрд╡реЗрджрди рдХреА рдореБрдЦреНрдп рд╡рд┐рдВрдбреЛ рдореЗрдВ, рдПрдХ рдЯреЗрдк рд▓реЛрдб рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдкреЙрдк-рдЕрдк рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдпрд╛ рдХреБрдЫ рд╕реНрдХреНрд░реАрди рдкрд░ рдПрдХ рдПрдирд┐рдореЗрдЯреЗрдб рд╕рдВрдХреНрд░рдордг рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдЖрдЧреЗ, рдореИрдВ рд╣рдорд╛рд░реА рдЪреБрдиреА рд╣реБрдИ рд╡рд┐рдзрд┐ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рдмрд╛рдд рдХрд░реВрдВрдЧрд╛, рдЬрд┐рд╕рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЪрд░рдг рд╣реИрдВ:

  • рдПрдХ рдЫрдк рд╕реНрдХреНрд░реАрди рддреИрдпрд╛рд░ рдХрд░рдирд╛ред
  • рдЙрдкрд╕реНрдерд┐рддрд┐ рдХрд╛ рдПрдиреАрдореЗрд╢рдиред
  • рдПрдиреАрдореЗрд╢рди рдЫрд┐рдкрд╛рдПрдБред

рд╕реНрдкрд▓реИрд╢ рд╕реНрдХреНрд░реАрди рддреИрдпрд╛рд░реА


рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ рдЖрдкрдХреЛ рдПрдХ рд╕реНрдерд┐рд░ рдЫрдк рд╕реНрдХреНрд░реАрди рддреИрдпрд╛рд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ - рд╡рд╣ рд╣реИ, рдПрдХ рд╕реНрдХреНрд░реАрди рдЬреЛ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рд╢реБрд░реВ рд╣реЛрдиреЗ рдкрд░ рддреБрд░рдВрдд рдкреНрд░рдХрдЯ рд╣реЛрддреА рд╣реИред рдЖрдк рдЗрд╕реЗ рджреЛ рддрд░реАрдХреЛрдВ рд╕реЗ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ : рдкреНрд░рддреНрдпреЗрдХ рдбрд┐рд╡рд╛рдЗрд╕ рдХреЗ рд▓рд┐рдП рдЕрд▓рдЧ-рдЕрд▓рдЧ рд░рд┐рдЬрд╝реЙрд▓реНрдпреВрд╢рди рдХреА рдЫрд╡рд┐рдпрд╛рдВ рдкреНрд░рджрд╛рди рдХрд░реЗрдВ, рдпрд╛ LaunchScreen.storyboard рдореЗрдВ рдЗрд╕ рд╕реНрдХреНрд░реАрди рдХреЛ LaunchScreen.storyboard ред рджреВрд╕рд░рд╛ рд╡рд┐рдХрд▓реНрдк Apple рджреНрд╡рд╛рд░рд╛ рд╕реНрд╡рдпрдВ рдЕрдзрд┐рдХ рддреЗрдЬрд╝, рдЕрдзрд┐рдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдФрд░ рдЕрдиреБрд╢рдВрд╕рд┐рдд рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ:


рд╕рдм рдХреБрдЫ рд╕рд░рд▓ рд╣реИ: рдПрдХ рд▓реЛрдЧреЛ рдХреЗ рд╕рд╛рде рдПрдХ рдврд╛рд▓ рдкреГрд╖реНрдарднреВрдорд┐ рдФрд░ imageView рд╕рд╛рде imageView ред

рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ, рдпрд╣ рд╕реНрдХреНрд░реАрди рдПрдирд┐рдореЗрдЯреЗрдб рдирд╣реАрдВ рд╣реЛ рд╕рдХрддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЖрдкрдХреЛ рдПрдХ рдФрд░, рд╕рдорд╛рди рд░реВрдк рд╕реЗ рд╕рдорд╛рди рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддрд╛рдХрд┐ рдЙрдирдХреЗ рдмреАрдЪ рдХрд╛ рд╕рдВрдХреНрд░рдордг рдЕрджреГрд╢реНрдп рд╣реЛред Main.storyboard рдореЗрдВ рдПрдХ ViewController рдЬреЛрдбрд╝реЗрдВ:


рдкрд┐рдЫрд▓реА рд╕реНрдХреНрд░реАрди рд╕реЗ рдЕрдВрддрд░ рдпрд╣ рд╣реИ рдХрд┐ рдПрдХ рдФрд░ imageView рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рдкрд╛рда рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рдЗрд╕реЗ рд╢реБрд░реВ рдореЗрдВ рдЫрд┐рдкрд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛)ред рдЕрдм рдЗрд╕ рдирд┐рдпрдВрддреНрд░рдХ рдХреЗ рд▓рд┐рдП рдПрдХ рдХреНрд▓рд╛рд╕ рдмрдирд╛рдПрдБ:

 final class SplashViewController: UIViewController { @IBOutlet weak var logoImageView: UIImageView! @IBOutlet weak var textImageView: UIImageView! var textImage: UIImage? override func viewDidLoad() { super.viewDidLoad() textImageView.image = textImage } } 

рдЬрд┐рди рддрддреНрд╡реЛрдВ рдХреЛ рд╣рдо рдЪреЗрддрди рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдЙрдирдХреЗ рд▓рд┐рдП IBOutlet рдЕрд▓рд╛рд╡рд╛, рдЗрд╕ рд╡рд░реНрдЧ рдореЗрдВ рдПрдХ textImage рдЧреБрдг рднреА рд╣реИ - рдПрдХ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд░реВрдк рд╕реЗ рдЪрдпрдирд┐рдд рдЪрд┐рддреНрд░ рдЗрд╕реЗ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдЕрдм рд╣рдо Main.storyboard рд╡рд╛рдкрд╕ Main.storyboard рдФрд░ SplashViewController рдХреНрд▓рд╛рд╕ рдХреЛ рд╕рдВрдмрдВрдзрд┐рдд рдХрдВрдЯреНрд░реЛрд▓рд░ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдЙрд╕реА рд╕рдордп, рдкреНрд░рд╛рд░рдВрднрд┐рдХ ViewController рдореЗрдВ рдпреВрд▓рд╛ рдХреЗ рд╕реНрдХреНрд░реАрдирд╢реЙрдЯ рдХреЗ рд╕рд╛рде рдПрдХ imageView рддрд╛рдХрд┐ рд╕реНрдкреНрд▓реИрд╢ рдХреЗ рдиреАрдЪреЗ рдХреЛрдИ рдЦрд╛рд▓реА рд╕реНрдХреНрд░реАрди рди рд╣реЛред

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

 protocol SplashPresenterDescription: class { func present() func dismiss(completion: @escaping () -> Void) } final class SplashPresenter: SplashPresenterDescription { func present() { //     } func dismiss(completion: @escaping () -> Void) { //     } } 

рдПрдХ рд╣реА рд╡рд╕реНрддреБ рдЫрдк рд╕реНрдХреНрд░реАрди рдХреЗ рд▓рд┐рдП рдкрд╛рда рдХрд╛ рдЪрдпрди рдХрд░реЗрдЧреАред рдкрд╛рда рдХреЛ рдЪрд┐рддреНрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЖрдкрдХреЛ Assets.xcassets рдореЗрдВ рдЙрдкрдпреБрдХреНрдд рд╕рдВрд╕рд╛рдзрди рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреЗ рдирд╛рдо рд╕рдорд╛рди рд╣реИрдВ, рд╕рдВрдЦреНрдпрд╛ рдХреЛ рдЫреЛрдбрд╝рдХрд░ - рдпрд╣ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд░реВрдк рд╕реЗ рдЙрддреНрдкрдиреНрди рд╣реЛрдЧрд╛:

  private lazy var textImage: UIImage? = { let textsCount = 17 let imageNumber = Int.random(in: 1...textsCount) let imageName = "i-splash-text-\(imageNumber)" return UIImage(named: imageName) }() 

рдпрд╣ рд╕рдВрдпреЛрдЧ рд╕реЗ рдирд╣реАрдВ рдерд╛ рдХрд┐ рдореИрдВрдиреЗ textImage рдХреЛ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рд╕рдВрдкрддреНрддрд┐ рдирд╣реАрдВ рдмрдирд╛рдпрд╛, рдЕрд░реНрдерд╛рддреН lazy , рдмрд╛рдж рдореЗрдВ рдЖрдк рд╕рдордЭреЗрдВрдЧреЗ рдХрд┐ рдХреНрдпреЛрдВред

рд╢реБрд░реБрдЖрдд рдореЗрдВ, рдореИрдВрдиреЗ рд╡рд╛рджрд╛ рдХрд┐рдпрд╛ рдерд╛ рдХрд┐ рд╕реНрдкреНрд▓реИрд╢ рд╕реНрдХреНрд░реАрди рдХреЛ рдЕрд▓рдЧ UIWindow рдореЗрдВ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЗрд╕рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рдЪрд╛рд╣рд┐рдП:

  • UIWindow рдмрдирд╛рдПрдВ;
  • SplashViewController рдФрд░ рдЗрд╕реЗ rootViewController `рдУрдо;
  • windowLevel рдХреЛ .normal (рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рди) рд╕реЗ рдмрдбрд╝рд╛ windowLevel рддрд╛рдХрд┐ рдпрд╣ рд╡рд┐рдВрдбреЛ рдореБрдЦреНрдп рдХреЗ рдКрдкрд░ рджрд┐рдЦрд╛рдИ рджреЗред

SplashPresenter рдЬреЛрдбрд╝реЗрдВ:

  private lazy var foregroundSplashWindow: UIWindow = { let splashViewController = self.splashViewController(with: textImage) let splashWindow = self.splashWindow(windowLevel: .normal + 1, rootViewController: splashViewController) return splashWindow }() private func splashWindow(windowLevel: UIWindow.Level, rootViewController: SplashViewController?) -> UIWindow { let splashWindow = UIWindow(frame: UIScreen.main.bounds) splashWindow.windowLevel = windowLevel splashWindow.rootViewController = rootViewController return splashWindow } private func splashViewController(with textImage: UIImage?) -> SplashViewController? { let storyboard = UIStoryboard(name: "Main", bundle: nil) let viewController = storyboard.instantiateViewController(withIdentifier: "SplashViewController") let splashViewController = viewController as? SplashViewController splashViewController?.textImage = textImage return splashViewController } 

рдЖрдкрдХреЛ рдпрд╣ рдЕрдЬреАрдм рд▓рдЧ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ splashViewController рдФрд░ splashWindow рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдЕрд▓рдЧ-рдЕрд▓рдЧ рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ splashWindow рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдмрд╛рдж рдореЗрдВ рдпрд╣ рдХрд╛рдо рдЖрдПрдЧрд╛ред

рд╣рдордиреЗ рдЕрднреА рддрдХ рдПрдирд┐рдореЗрд╢рди рд▓реЙрдЬрд┐рдХ рд▓рд┐рдЦрдирд╛ рд╢реБрд░реВ рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИ рдФрд░ SplashPresenter рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдмрд╣реБрдд рд╕рд╛рд░реЗ рдХреЛрдб рд╣реИрдВред рдЗрд╕рд▓рд┐рдП, рдореИрдВ рдПрдХ рдРрд╕реА рд╕рдВрд╕реНрдерд╛ рдмрдирд╛рдиреЗ рдХрд╛ рдкреНрд░рд╕реНрддрд╛рд╡ рдХрд░рддрд╛ рд╣реВрдВ рдЬреЛ рд╕реАрдзреЗ рддреМрд░ рдкрд░ рдПрдиреАрдореЗрд╢рди рд╕реЗ рдирд┐рдкрдЯреЗрдЧреА (рд╕рд╛рде рд╣реА рдЬрд┐рдореНрдореЗрджрд╛рд░рд┐рдпреЛрдВ рдХрд╛ рдпрд╣ рд╡рд┐рднрд╛рдЬрди):

 protocol SplashAnimatorDescription: class { func animateAppearance() func animateDisappearance(completion: @escaping () -> Void) } final class SplashAnimator: SplashAnimatorDescription { private unowned let foregroundSplashWindow: UIWindow private unowned let foregroundSplashViewController: SplashViewController init(foregroundSplashWindow: UIWindow) { self.foregroundSplashWindow = foregroundSplashWindow guard let foregroundSplashViewController = foregroundSplashWindow.rootViewController as? SplashViewController else { fatalError("Splash window doesn't have splash root view controller!") } self.foregroundSplashViewController = foregroundSplashViewController } func animateAppearance() { //     } func animateDisappearance(completion: @escaping () -> Void) { //     } 

rootViewController рдХреЛ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЛ рдкрд╛рд╕ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП, rootViewController рдХреЛ рдЗрд╕рд╕реЗ "рдПрдХреНрд╕рдЯреНрд░реИрдХреНрдЯреЗрдб" рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рдЧреБрдг рдореЗрдВ рднреА рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреИрд╕реЗ рдХрд┐ foregroundSplashViewController rootViewController ред

SplashPresenter рдЬреЛрдбрд╝реЗрдВ:

  private lazy var animator: SplashAnimatorDescription = SplashAnimator(foregroundSplashWindow: foregroundSplashWindow) 

рдФрд░ рдЙрд╕рдХреЗ present рдФрд░ dismiss рдареАрдХ рдХрд░реЗрдВ:

  func present() { animator.animateAppearance() } func dismiss(completion: @escaping () -> Void) { animator.animateDisappearance(completion: completion) } 

рд╕рдм рдХреБрдЫ, рдкреАрдЫреЗ рд╕рдмрд╕реЗ рдЙрдмрд╛рдК рд╣рд┐рд╕реНрд╕рд╛, рдЖрдк рдЕрдВрдд рдореЗрдВ рдПрдиреАрдореЗрд╢рди рд╢реБрд░реВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ!

рд╕реВрд░рдд рдПрдиреАрдореЗрд╢рди


рдЪрд▓реЛ рдЫрдк рд╕реНрдХреНрд░реАрди рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ рдХреЗ рдПрдиреАрдореЗрд╢рди рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, рдпрд╣ рд╕рд░рд▓ рд╣реИ:

  • рд▓реЛрдЧреЛ logoImageView ( logoImageView )ред
  • рдкрд╛рда fader рдкрд░ рдкреНрд░рдХрдЯ рд╣реЛрддрд╛ рд╣реИ рдФрд░ рдереЛрдбрд╝рд╛ рд╕рд╛ рдЙрдЧрддрд╛ рд╣реИ ( textImageView )ред

рдЖрдкрдХреЛ рдпрд╛рдж рджрд┐рд▓рд╛ рджреВрдВ рдХрд┐ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ UIWindow рдХреЛ рдЕрджреГрд╢реНрдп рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдЗрд╕реЗ рдареАрдХ рдХрд░рдиреЗ рдХреЗ рджреЛ рддрд░реАрдХреЗ рд╣реИрдВ:

  • рдЙрд╕ рдкрд░ makeKeyAndVisible рдореЗрдердб makeKeyAndVisible рдХреЙрд▓ рдХрд░реЗрдВ;
  • рд╕реЗрдЯ рд╕рдВрдкрддреНрддрд┐ред isHidden = false ред

рджреВрд╕рд░реА рд╡рд┐рдзрд┐ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдЙрдкрдпреБрдХреНрдд рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╣рдо рдирд╣реАрдВ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдХрд┐ keyWindow ред

рдЗрд╕реЗ SplashAnimator рдореЗрдВ SplashAnimator animateAppearance() рдореЗрдВ animateAppearance() рд╡рд┐рдзрд┐ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ:

  func animateAppearance() { foregroundSplashWindow.isHidden = false foregroundSplashViewController.textImageView.transform = CGAffineTransform(translationX: 0, y: 20) UIView.animate(withDuration: 0.3, animations: { self.foregroundSplashViewController.logoImageView.transform = CGAffineTransform(scaleX: 88 / 72, y: 88 / 72) self.foregroundSplashViewController.textImageView.transform = .identity }) foregroundSplashViewController.textImageView.alpha = 0 UIView.animate(withDuration: 0.15, animations: { self.foregroundSplashViewController.textImageView.alpha = 1 }) } 

рдореБрдЭреЗ рдЖрдкрдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкрддрд╛ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВ рдЬрд▓реНрдж рд╕реЗ рдЬрд▓реНрдж рдЗрд╕ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛ рд╢реБрд░реВ рдХрд░рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ рдФрд░ рджреЗрдЦреВрдВрдЧрд╛ рдХрд┐ рдХреНрдпрд╛ рд╣реБрдЖ! рдпрд╣ рдХреЗрд╡рд▓ AppDelegate рдЦреЛрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдиреА рд╣реБрдИ рд╣реИ, splashPresenter рд╕рдВрдкрддреНрддрд┐ рдХреЛ рдЬреЛрдбрд╝реЗрдВ рдФрд░ рдЙрд╕ рдкрд░ present рдкрджреНрдзрддрд┐ рдХреЛ рдХреЙрд▓ рдХрд░реЗрдВред рдЙрд╕реА рд╕рдордп, 2 рд╕реЗрдХрдВрдб рдХреЗ рдмрд╛рдж, рд╣рдо dismiss рдХреЛ рдХреЙрд▓ рдХрд░реЗрдВрдЧреЗ рддрд╛рдХрд┐ рд╣рдореЗрдВ рдЗрд╕ рдлрд╝рд╛рдЗрд▓ рдкрд░ рд╡рд╛рдкрд╕ рди рд▓реМрдЯрдирд╛ рдкрдбрд╝реЗ:

  private var splashPresenter: SplashPresenter? = SplashPresenter() func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { splashPresenter?.present() let delay: TimeInterval = 2 DispatchQueue.main.asyncAfter(deadline: .now() + delay) { self.splashPresenter?.dismiss { [weak self] in self?.splashPresenter = nil } } return true } 

рд╕реНрдкреНрд▓реИрд╢ рдХреЛ рдЫрд┐рдкрд╛рдиреЗ рдХреЗ рдмрд╛рдж рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдореЗрдореЛрд░реА рд╕реЗ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рд╣реБрд░реНрд░реЗ, рдЖрдк рдЪрд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВ!


рдЫрд┐рдкрдиреЗ рдХрд╛ рдПрдиреАрдореЗрд╢рди


рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ (рдпрд╛ рд╕реМрднрд╛рдЧреНрдп рд╕реЗ), рдХреЛрдб рдХреА 10 рд▓рд╛рдЗрдиреЗрдВ рдЫрд┐рдкрдиреЗ рдХреЗ рдПрдиреАрдореЗрд╢рди рдХрд╛ рд╕рд╛рдордирд╛ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреАред рдЫреЗрдж рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдмрдирд╛рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдЬреЛ рдЕрднреА рднреА рдШреВрдореЗрдЧрд╛ рдФрд░ рдмрдврд╝реЗрдЧрд╛! рдЕрдЧрд░ рдЖрдкрдХреЛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ "рдпрд╣ рдПрдХ рдореБрдЦреМрдЯрд╛ рдХреЗ рд╕рд╛рде рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ", рддреЛ рдЖрдк рдмрд┐рд▓реНрдХреБрд▓ рд╕рд╣реА рд╣реИрдВ!

рд╣рдо рдореБрдЦреНрдп рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╡рд┐рдВрдбреЛ рдХреА layer рдПрдХ рдореБрдЦреМрдЯрд╛ рдЬреЛрдбрд╝ рджреЗрдВрдЧреЗ (рд╣рдо рдХрд┐рд╕реА рд╡рд┐рд╢рд┐рд╖реНрдЯ рдирд┐рдпрдВрддреНрд░рдХ рд╕реЗ рдмрдВрдзрдирд╛ рдирд╣реАрдВ рдЪрд╛рд╣рддреЗ)ред рдЖрдЗрдП рдЗрд╕реЗ рддреБрд░рдВрдд рдХрд░реЗрдВ, рдФрд░ рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ foregroundSplashWindow рдЫрд┐рдкрд╛рдирд╛ред

  func animateDisappearance(completion: @escaping () -> Void) { guard let window = UIApplication.shared.delegate?.window, let mainWindow = window else { fatalError("Application doesn't have a window!") } foregroundSplashWindow.alpha = 0 let mask = CALayer() mask.frame = foregroundSplashViewController.logoImageView.frame mask.contents = SplashViewController.logoImageBig.cgImage mainWindow.layer.mask = mask } 

рдпрд╣рд╛рдВ рдпрд╣ рдзреНрдпрд╛рди рд░рдЦрдирд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдХрд┐ рдореИрдВрдиреЗ foregroundSplashWindow рдХреЛ рдЫреБрдкрд╛ рджрд┐рдпрд╛ред рдПрдХ рдФрд░ рджрд┐рд▓рдЪрд╕реНрдк рдмрд┐рдВрджреБ: рдЪреВрдВрдХрд┐ рдпрд╣ рдореБрдЦреМрдЯрд╛ рдПрдиреАрдореЗрд╢рди рдХреЗ рджреМрд░рд╛рди рдмрдврд╝реЗрдЧрд╛, рдЖрдкрдХреЛ рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рдЙрдЪреНрдЪ рд░рд┐рдЬрд╝реЙрд▓реНрдпреВрд╢рди рд▓реЛрдЧреЛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, 1024x1024)ред рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ SplashViewController рдЬреЛрдбрд╝рд╛:

  static let logoImageBig: UIImage = UIImage(named: "splash-logo-big")! 

рджреЗрдЦрд┐рдП рдХреНрдпрд╛ рд╣реБрдЖ?


рдореБрдЭреЗ рдкрддрд╛ рд╣реИ, рдЕрдм рдпрд╣ рдмрд╣реБрдд рдкреНрд░рднрд╛рд╡рд╢рд╛рд▓реА рдирд╣реАрдВ рджрд┐рдЦрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рдм рдХреБрдЫ рдЖрдЧреЗ рд╣реИ, рд╣рдо рдЖрдЧреЗ рдмрдврд╝рддреЗ рд╣реИрдВ! рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдЪреМрдХрд╕ рджреЗрдЦ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдПрдиреАрдореЗрд╢рди рдХреЗ рджреМрд░рд╛рди рд▓реЛрдЧреЛ рддреБрд░рдВрдд рдкрд╛рд░рджрд░реНрд╢реА рдирд╣реАрдВ рдмрдирддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХреБрдЫ рд╕рдордп рдХреЗ рд▓рд┐рдПред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, imageView subviews рд╕рднреА imageView рд╢реАрд░реНрд╖ рдкрд░ subviews рдПрдХ рд▓реЛрдЧреЛ рдХреЗ рд╕рд╛рде рдПрдХ imageView рдЬреЛрдбрд╝реЗрдВ рдЬреЛ рдлреАрдХрд╛ рджреНрд╡рд╛рд░рд╛ рдЫрд┐рдкрд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

  let maskBackgroundView = UIImageView(image: SplashViewController.logoImageBig) maskBackgroundView.frame = mask.frame mainWindow.addSubview(maskBackgroundView) mainWindow.bringSubviewToFront(maskBackgroundView) 

рддреЛ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд▓реЛрдЧреЛ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рдЫреЗрдж рд╣реИ, рдФрд░ рдЫреЗрдж рдХреЗ рдиреАрдЪреЗ рд╣реА рд▓реЛрдЧреЛ рд╣реИред


рдЕрдм рдПрдХ рд╕реБрдВрджрд░ рдврд╛рд▓ рдкреГрд╖реНрдарднреВрдорд┐ рдФрд░ рдкрд╛рда рдХреЗ рд╕реНрдерд╛рди рдкрд░ рд╡рд╛рдкрд╕ рдЬрд╛рдПрдВред рдХрд┐рд╕реА рднреА рд╡рд┐рдЪрд╛рд░ рдпрд╣ рдХреИрд╕реЗ рдХрд░рдирд╛ рд╣реИ?
рдореЗрд░реЗ рдкрд╛рд╕: windowLevel рддрд╣рдд рдПрдХ рдФрд░ UIWindow (рдЬреЛ рдХрд┐ рдПрдХ рдЫреЛрдЯреА windowLevel рд╕рд╛рде рд╣реИ, рдЪрд▓реЛ рдЗрд╕реЗ backgroundSplashWindow рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВ), рдФрд░ рдлрд┐рд░ рд╣рдо рдЗрд╕реЗ рдмреНрд▓реИрдХ рдмреИрдХрдЧреНрд░рд╛рдЙрдВрдб рдХреЗ рдмрдЬрд╛рдп рджреЗрдЦреЗрдВрдЧреЗред рдФрд░, рдЬрд╝рд╛рд╣рд┐рд░ рд╣реИ, rootViewController' рдореЗрдВ рдПрдХ SplashViewContoller , рдХреЗрд╡рд▓ рдЖрдкрдХреЛ logoImageView рдХреЛ рдЫрд┐рдкрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, SplashViewController рдореЗрдВ рдПрдХ рд╕рдВрдкрддреНрддрд┐ SplashViewController :

  var logoIsHidden: Bool = false 

рдФрд░ viewDidLoad() рд╡рд┐рдзрд┐ рдореЗрдВ, рдЬреЛрдбрд╝реЗрдВ:

  logoImageView.isHidden = logoIsHidden 

SplashPresenter рдЕрдВрддрд┐рдо рд░реВрдк SplashPresenter : splashViewController (with textImage: UIImage?) рдПрдХ рдФрд░ logoIsHidden: Bool рдЬреЛрдбрд╝реЗрдВ logoIsHidden: Bool рдкреИрд░рд╛рдореАрдЯрд░, рдЬрд┐рд╕реЗ SplashViewController рдкрд░ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

 splashViewController?.logoIsHidden = logoIsHidden 

рддрджрдиреБрд╕рд╛рд░, рдЬрд╣рд╛рдВ foregroundSplashWindow рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЗрд╕ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд▓рд┐рдП false рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдФрд░ backgroundSplashWindow рд▓рд┐рдП true

  private lazy var backgroundSplashWindow: UIWindow = { let splashViewController = self.splashViewController(with: textImage, logoIsHidden: true) let splashWindow = self.splashWindow(windowLevel: .normal - 1, rootViewController: splashViewController) return splashWindow }() 

рдЖрдкрдХреЛ рдЗрд╕ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ SplashAnimator рдореЗрдВ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдлреЗрдВрдХрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ ( foregroundSplashWindow рд╕рдорд╛рди)ред

  private unowned let backgroundSplashWindow: UIWindow private unowned let backgroundSplashViewController: SplashViewController 

рддрд╛рдХрд┐ рдПрдХ рдХрд╛рд▓реЗ рд░рдВрдЧ рдХреА рдкреГрд╖реНрдарднреВрдорд┐ рдХреЗ рдмрдЬрд╛рдп рд╣рдо рдПрдХ рд╣реА рд╕реНрдкрд▓реИрд╢ рд╕реНрдХреНрд░реАрди рджреЗрдЦреЗрдВ, foregroundSplashWindow рдЫрд┐рдкрдиреЗ рд╕реЗ рдареАрдХ рдкрд╣рд▓реЗред рдЖрдкрдХреЛ backgroundSplashWindow рджрд┐рдЦрд╛рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИред

  backgroundSplashWindow.isHidden = false 

рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рдпреЛрдЬрдирд╛ рд╕рдлрд▓ рд░рд╣реА:


рдЕрдм рд╕рдмрд╕реЗ рджрд┐рд▓рдЪрд╕реНрдк рд╣рд┐рд╕реНрд╕рд╛ рдЫрд┐рдкрд╛ рд╣реБрдЖ рдПрдиреАрдореЗрд╢рди рд╣реИ! рдЪреВрдБрдХрд┐ рдЖрдкрдХреЛ CALayer рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, UIView рдирд╣реАрдВ, рд╣рдо рдорджрдж рдХреЗ рд▓рд┐рдП CoreAnimation рдУрд░ рд░реБрдЦ рдХрд░реЗрдВрдЧреЗред рдЪрд▓реЛ рд░реЛрдЯреЗрд╢рди рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ:

  private func addRotationAnimation(to layer: CALayer, duration: TimeInterval, delay: CFTimeInterval = 0) { let animation = CABasicAnimation() let tangent = layer.position.y / layer.position.x let angle = -1 * atan(tangent) animation.beginTime = CACurrentMediaTime() + delay animation.duration = duration animation.valueFunction = CAValueFunction(name: CAValueFunctionName.rotateZ) animation.fromValue = 0 animation.toValue = angle animation.isRemovedOnCompletion = false animation.fillMode = CAMediaTimingFillMode.forwards layer.add(animation, forKey: "transform") } 

рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рд░реЛрдЯреЗрд╢рди рдХреЛрдг рдХреА рдЧрдгрдирд╛ рд╕реНрдХреНрд░реАрди рдХреЗ рдЖрдХрд╛рд░ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХреА рдЬрд╛рддреА рд╣реИ, рддрд╛рдХрд┐ рд╕рднреА рдЙрдкрдХрд░рдгреЛрдВ рдкрд░ рдпреВрд▓рд╛ рдКрдкрд░реА рдмрд╛рдПрдВ рдХреЛрдиреЗ рдореЗрдВ рдШреВрдорддреА рд╣реИред

рд▓реЛрдЧреЛ рд╕реНрдХреЗрд▓рд┐рдВрдЧ рдПрдиреАрдореЗрд╢рди:

  private func addScalingAnimation(to layer: CALayer, duration: TimeInterval, delay: CFTimeInterval = 0) { let animation = CAKeyframeAnimation(keyPath: "bounds") let width = layer.frame.size.width let height = layer.frame.size.height let coefficient: CGFloat = 18 / 667 let finalScale = UIScreen.main.bounds.height * coeficient let scales = [1, 0.85, finalScale] animation.beginTime = CACurrentMediaTime() + delay animation.duration = duration animation.keyTimes = [0, 0.2, 1] animation.values = scales.map { NSValue(cgRect: CGRect(x: 0, y: 0, width: width * $0, height: height * $0)) } animation.timingFunctions = [CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut), CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut)] animation.isRemovedOnCompletion = false animation.fillMode = CAMediaTimingFillMode.forwards layer.add(animation, forKey: "scaling") } 

рдпрд╣ finalScale рдзреНрдпрд╛рди рджреЗрдиреЗ finalScale : рдЕрдВрддрд┐рдо рдкреИрдорд╛рдиреЗ рдХреА рдЧрдгрдирд╛ рд╕реНрдХреНрд░реАрди рдХреЗ рдЖрдХрд╛рд░ (рдКрдВрдЪрд╛рдИ рдХреЗ рдЕрдиреБрдкрд╛рдд рдореЗрдВ) рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рднреА рдХреА рдЬрд╛рддреА рд╣реИред рдпрд╣реА рд╣реИ, 667 рдЕрдВрдХ (iPhone 6) рдХреА рд╕реНрдХреНрд░реАрди рдКрдВрдЪрд╛рдИ рдХреЗ рд╕рд╛рде, рдпреВрд▓рд╛ рдХреЛ 18 рдЧреБрдирд╛ рдмрдврд╝рдирд╛ рдЪрд╛рд╣рд┐рдПред

рд▓реЗрдХрд┐рди рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдпрд╣ рдереЛрдбрд╝рд╛ рдХрдо рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ ( scales рдФрд░ keyTimes рдореЗрдВ рджреВрд╕рд░реЗ рддрддреНрд╡реЛрдВ рдХреЗ рдЕрдиреБрд╕рд╛рд░)ред рдпрд╣реА рд╣реИ, рдЙрд╕ рд╕рдордп 0.2 * duration (рдЬрд╣рд╛рдВ duration рд╕реНрдХреЗрд▓рд┐рдВрдЧ рдПрдиреАрдореЗрд╢рди рдХреА рдХреБрд▓ рдЕрд╡рдзрд┐ рд╣реИ), рдпреБрд▓рд╛ рдХрд╛ рдкреИрдорд╛рдирд╛ 0.85 рд╣реЛрдЧрд╛ред

рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдлрд┐рдирд┐рд╢ рд▓рд╛рдЗрди рдкрд░ рд╣реИрдВ! animateDisappearance рд╡рд┐рдзрд┐ рдореЗрдВ animateDisappearance рд╕рднреА рдПрдирд┐рдореЗрд╢рди рдЪрд▓рд╛рдПрдВ:

1) рдореБрдЦреНрдп рд╡рд┐рдВрдбреЛ ( mainWindow ) рдХреА рд╕реНрдХреЗрд▓рд┐рдВрдЧред
2) рд░реЛрдЯреЗрд╢рди, рд╕реНрдХреЗрд▓рд┐рдВрдЧ, рд▓реЛрдЧреЛ рдХрд╛ рдЧрд╛рдпрдм рд╣реЛрдирд╛ ( maskBackgroundView )ред
3) рд░реЛрдЯреЗрд╢рди, "рдЫреЗрдж" ( mask ) рдХреЗ рд╕реНрдХреЗрд▓рд┐рдВрдЧред
4) рдкрд╛рда рдХрд╛ рдЧрд╛рдпрдм рд╣реЛрдирд╛ ( textImageView )ред

  CATransaction.setCompletionBlock { mainWindow.layer.mask = nil completion() } CATransaction.begin() mainWindow.transform = CGAffineTransform(scaleX: 1.05, y: 1.05) UIView.animate(withDuration: 0.6, animations: { mainWindow.transform = .identity }) [mask, maskBackgroundView.layer].forEach { layer in addScalingAnimation(to: layer, duration: 0.6) addRotationAnimation(to: layer, duration: 0.6) } UIView.animate(withDuration: 0.1, delay: 0.1, options: [], animations: { maskBackgroundView.alpha = 0 }) { _ in maskBackgroundView.removeFromSuperview() } UIView.animate(withDuration: 0.3) { self.backgroundSplashViewController.textImageView.alpha = 0 } CATransaction.commit() 

рдПрдиреАрдореЗрд╢рди рдХреЛ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореИрдВрдиреЗ CATransaction рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ CAAnimation рддреБрд▓рдирд╛ рдореЗрдВ рдЕрдзрд┐рдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ CAAnimation рдорд╛рдзреНрдпрдо рд╕реЗ рд╕рднреА рдПрдирд┐рдореЗрд╢рди рдирд╣реАрдВ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред


рдирд┐рд╖реНрдХрд░реНрд╖


рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдЖрдЙрдЯрдкреБрдЯ рдореЗрдВ рд╣рдореЗрдВ рдПрдХ рдШрдЯрдХ рдорд┐рд▓рд╛ рд╣реИ рдЬреЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд▓реЙрдиреНрдЪ рдХреЗ рд╕рдВрджрд░реНрдн рдкрд░ рдирд┐рд░реНрднрд░ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ (рдЪрд╛рд╣реЗ рд╡рд╣ рдПрдХ рдбрд┐рдкреНрд▓реЛрдорд╛ рдерд╛, рдПрдХ рдзрдХреНрдХрд╛ рдЕрдзрд┐рд╕реВрдЪрдирд╛, рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рд╢реБрд░реБрдЖрдд, рдпрд╛ рдХреБрдЫ рдФрд░)ред рдПрдиреАрдореЗрд╢рди рд╡реИрд╕реЗ рднреА рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдХрд╛рдо рдХрд░реЗрдЧрд╛!

рдЖрдк рдпрд╣рд╛рдВ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

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


All Articles