
рд╣рд╛рдп рд╣рдорд░!
рдореИрдВ рд╕реНрдкреНрд▓реИрд╢ рд╕реНрдХреНрд░реАрди рд╕реЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдЕрдиреНрдп рд╕реНрдХреНрд░реАрди рдкрд░ рдПрдиреАрдореЗрд╢рди рд╕рдВрдХреНрд░рдордг рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реВрдВрдЧрд╛ред рдпрд╣ рдХрд╛рд░реНрдп рдПрдХ рд╡реИрд╢реНрд╡рд┐рдХ рд░реАрдмреНрд░рд╛рдВрдбрд┐рдВрдЧ рдХреЗ рднрд╛рдЧ рдХреЗ рд░реВрдк рдореЗрдВ рд╣реБрдЖ, рдЬреЛ рдХрд┐ рд╕реНрдкреНрд▓реИрд╢ рд╕реНрдХреНрд░реАрди рдФрд░ рдЙрддреНрдкрд╛рдж рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ рдХреЛ рдмрджрд▓реЗ рдмрд┐рдирд╛ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ рдерд╛ред
рдмрдбрд╝реА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдХрдИ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЗ рд▓рд┐рдП, рд╕реБрдВрджрд░ рдПрдирд┐рдореЗрд╢рди рдмрдирд╛рдиреЗ рд╕реЗ рдЬреБрдбрд╝реА рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░рдирд╛ рдХреАрдбрд╝реЗ, рдЬрдЯрд┐рд▓ рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдФрд░ рдЧрд░реНрдо рдлрд┐рдХреНрд╕ рдХреА рджреБрдирд┐рдпрд╛ рдореЗрдВ рддрд╛рдЬреА рд╣рд╡рд╛ рдХреА рд╕рд╛рдВрд╕ рдмрди рдЬрд╛рддрд╛ рд╣реИред рдРрд╕реЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдЕрдкреЗрдХреНрд╖рд╛рдХреГрдд рдЖрд╕рд╛рди рд╣реИ, рдФрд░ рдкрд░рд┐рдгрд╛рдо рдЖрдВрдЦ рдХреЛ рднрд╛рддрд╛ рд╣реИ рдФрд░ рдмрд╣реБрдд рдкреНрд░рднрд╛рд╡рд╢рд╛рд▓реА рджрд┐рдЦрддрд╛ рд╣реИ! рд▓реЗрдХрд┐рди рдРрд╕реЗ рд╕рдордп рд╣реЛрддреЗ рд╣реИрдВ рдЬрдм рдорд╛рдирдХ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд▓рд╛рдЧреВ рдирд╣реАрдВ рд╣реЛрддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рдЖрдкрдХреЛ рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреЗ рд╡рд░реНрдХрдЖрд░реНрд╕ рдХреЗ рд╕рд╛рде рдЖрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред
рдкрд╣рд▓реА рдирдЬрд╝рд░ рдореЗрдВ, рд╕реНрдкреНрд▓реИрд╢ рд╕реНрдХреНрд░реАрди рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреЗ рдХрд╛рд░реНрдп рдореЗрдВ, рдПрдиреАрдореЗрд╢рди рдХрд╛ рдирд┐рд░реНрдорд╛рдг рд╕рдмрд╕реЗ рдХрдард┐рди рдкреНрд░рддреАрдд рд╣реЛрддрд╛ рд╣реИ, рдФрд░ рдмрд╛рдХреА рд╕рдм "рдирд┐рдпрдорд┐рдд рджрд┐рдирдЪрд░реНрдпрд╛" рд╣реИред рдХреНрд▓рд╛рд╕рд┐рдХ рд╕реНрдерд┐рддрд┐: рдкрд╣рд▓реЗ рд╣рдо рдПрдХ рд╕реНрдХреНрд░реАрди рджрд┐рдЦрд╛рддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рдПрдХ рдХрд╕реНрдЯрдо рд╕рдВрдХреНрд░рдордг рдХреЗ рд╕рд╛рде рд╣рдо рдЕрдЧрд▓реЗ рдПрдХ рдХреЛ рдЦреЛрд▓рддреЗ рд╣реИрдВ - рд╕рдм рдХреБрдЫ рд╕рд░рд▓ рд╣реИ!
рдПрдиреАрдореЗрд╢рди рдХреЗ рднрд╛рдЧ рдХреЗ рд░реВрдк рдореЗрдВ, рдЖрдкрдХреЛ рд╕реНрдкреНрд▓реИрд╢ рд╕реНрдХреНрд░реАрди рдкрд░ рдПрдХ рдЫреЗрдж рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдЕрдЧрд▓реА рд╕реНрдХреНрд░реАрди рдХреА рд╕рд╛рдордЧреНрд░реА рдкреНрд░рджрд░реНрд╢рд┐рдд рд╣реЛрддреА рд╣реИ, рдЕрд░реНрдерд╛рдд, рд╣рдореЗрдВ рдпрд╣ рдЬрд╛рдирдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рд╕реНрдкреНрд▓реИрд╢ рдХреЗ рдиреАрдЪреЗ рдХреМрди рд╕рд╛
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() {
рдПрдХ рд╣реА рд╡рд╕реНрддреБ рдЫрдк рд╕реНрдХреНрд░реАрди рдХреЗ рд▓рд┐рдП рдкрд╛рда рдХрд╛ рдЪрдпрди рдХрд░реЗрдЧреАред рдкрд╛рда рдХреЛ рдЪрд┐рддреНрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЖрдкрдХреЛ
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() {
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
рдорд╛рдзреНрдпрдо рд╕реЗ рд╕рднреА рдПрдирд┐рдореЗрд╢рди рдирд╣реАрдВ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред
рдирд┐рд╖реНрдХрд░реНрд╖
рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдЖрдЙрдЯрдкреБрдЯ рдореЗрдВ рд╣рдореЗрдВ рдПрдХ рдШрдЯрдХ рдорд┐рд▓рд╛ рд╣реИ рдЬреЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд▓реЙрдиреНрдЪ рдХреЗ рд╕рдВрджрд░реНрдн рдкрд░ рдирд┐рд░реНрднрд░ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ (рдЪрд╛рд╣реЗ рд╡рд╣ рдПрдХ рдбрд┐рдкреНрд▓реЛрдорд╛ рдерд╛, рдПрдХ рдзрдХреНрдХрд╛ рдЕрдзрд┐рд╕реВрдЪрдирд╛, рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рд╢реБрд░реБрдЖрдд, рдпрд╛ рдХреБрдЫ рдФрд░)ред рдПрдиреАрдореЗрд╢рди рд╡реИрд╕реЗ рднреА рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдХрд╛рдо рдХрд░реЗрдЧрд╛!
рдЖрдк рдпрд╣рд╛рдВ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред