рдЖрдЬ рд╣рдо iOS рд╡рд┐рдХрд╛рд╕ рдореЗрдВ рд╡рд╛рд╕реНрддреБ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ, рдХреБрдЫ рдЪреАрдЬреЛрдВ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рдХреБрдЫ рдмрд╛рд░реАрдХрд┐рдпреЛрдВ рдФрд░ рд╡рд┐рдХрд╛рд╕ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реЗрдВрдЧреЗред рдореИрдВ рдЖрдкрдХреЛ рдмрддрд╛рддрд╛ рд╣реВрдВ рдХрд┐ рд╣рдо рдХрд┐рди рджреГрд╖реНрдЯрд┐рдХреЛрдгреЛрдВ рдХрд╛ рдкрд╛рд▓рди рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд╡рд┐рд╡рд░рдг рдореЗрдВ рдереЛрдбрд╝рд╛ рдЧрд╣рд░рд╛рдИ рд╕реЗ рдЬрд╛рддреЗ рд╣реИрдВред
рд╕рднреА рдХрд╛рд░реНрдбреЛрдВ рдХреЛ рддреБрд░рдВрдд рдкреНрд░рдХрдЯ рдХрд░реЗрдВред рд╣рдо MVVM-R (MVVM + Router) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред
рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдпрд╣ рдПрдХ рдирд┐рдпрдорд┐рдд рдПрдорд╡реАрд╡реАрдПрдо рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рд╕реНрдХреНрд░реАрди рдХреЗ рдмреАрдЪ рдиреЗрд╡рд┐рдЧреЗрд╢рди рдХреЛ рдПрдХ рдЕрд▓рдЧ рдкрд░рдд рдореЗрдВ рд░рдЦрд╛ рдЧрдпрд╛ рд╣реИ - рд░рд╛рдЙрдЯрд░, рдФрд░ рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рддрд░реНрдХ - рд╕реЗрд╡рд╛рдУрдВ рдореЗрдВред рдЕрдЧрд▓рд╛, рд╣рдо рдкреНрд░рддреНрдпреЗрдХ рдкрд░рдд рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рд╣рдорд╛рд░реА рдЙрдкрд▓рдмреНрдзрд┐рдпреЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗред
MVVM, VIPER рдпрд╛ MVC рдХреНрдпреЛрдВ рдирд╣реАрдВ?
рдПрдорд╡реАрд╕реА рдХреЗ рд╡рд┐рдкрд░реАрдд, MVVM рдХреА рдкрд░рддреЛрдВ рдХреЗ рдмреАрдЪ рдХрд╛рдлреА рд╡рд┐рднрд╛рдЬрд┐рдд рдЬрд┐рдореНрдореЗрджрд╛рд░реА рд╣реИред рдпрд╣ VIPER рдХреА рддрд░рд╣ рдХрдИ "рд╕реЗрд╡рд╛рд░рдд" рдХреЛрдб рдирд╣реАрдВ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рд╕реНрдХреНрд░реАрдирдореИрдбрд▓ рдлреЙрд░ рд╕реНрдХреНрд░реАрди рднреА рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рджреНрд╡рд╛рд░рд╛ рдмрдВрдж рд╣реИред рдпрд╣ рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдХреБрдЫ рд╣рдж рддрдХ VIPER рдХреЗ рд╕рдорд╛рди рд╣реИ, рдХреЗрд╡рд▓ рдкреНрд░рд╕реНрддреБрддрдХрд░реНрддрд╛ рдФрд░ рдЗрдВрдЯрд░реЗрдХреНрдЯрд░ ViewModel рдореЗрдВ рд╕рдВрдпреБрдХреНрдд рд╣реИрдВ, рдФрд░ рдкрд░рддреЛрдВ рдХреЗ рдмреАрдЪ рдХрдиреЗрдХреНрд╢рди рдХреЛ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рд╢реАрд▓ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдФрд░ рдмрд╛рдЗрдВрдбрд░реЛрдВ рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕рд░рд▓ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ (рд╣рдо ReactiveSwift рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ)ред
рд╕рддреНрддрд╛
рд╣рдо рдбреЗрдЯрд╛ рдореЙрдбрд▓ рдХреА рджреЛ рдкрд░рддреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ: рдкрд╣рд▓рд╛ рдПрдХ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рдЬреБрдбрд╝рд╛ рд╣реБрдЖ рд╣реИ (рдмрд╛рдж рдореЗрдВ рдкреНрд░рдмрдВрдзрд┐рдд рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рд╕рдВрджрд░реНрднрд┐рдд), рджреВрд╕рд░рд╛ рддрдерд╛рдХрдерд┐рдд рдкреНрд▓реЗрди рдСрдмреНрдЬреЗрдХреНрдЯ рд╣реИ , рдЬрд┐рд╕рдХрд╛ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рдХреЛрдИ рд▓реЗрдирд╛-рджреЗрдирд╛ рдирд╣реАрдВ рд╣реИред
рдкреНрд░рддреНрдпреЗрдХ рд╕рд╛рджрд╛ рдЗрдХрд╛рдИ рдЯреНрд░рд╛рдВрд╕рд▓реЗрдЯреЗрдмрд▓ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреА рд╣реИ, рдЬрд┐рд╕реЗ рдПрдХ рдкреНрд░рдмрдВрдзрд┐рдд рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реЗ рдЖрд░рдВрдн рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдЬрд┐рд╕рд╕реЗ рдПрдХ рдкреНрд░рдмрдВрдзрд┐рдд рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рд╣рдо Realm рдХрд╛ рдЙрдкрдпреЛрдЧ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд░рддреЗ рд╣реИрдВ, рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ ManagedObject
RealmSwift.Object
ред рдорд╛рдирдЪрд┐рддреНрд░рдг Codable
рдорд╛рдзреНрдпрдо рд╕реЗ рд╣реЛрддрд╛ рд╣реИ: рдЙрдиреНрд╣реЗрдВ рд╕рд╛рджреЗ рд╡рд╕реНрддреБрдУрдВ рдХреЗ рд░реВрдк рдореЗрдВ рдореИрдк рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдкреНрд░рдмрдВрдзрд┐рдд рд╡рд╕реНрддреБрдУрдВ рдХреЗ рд░реВрдк рдореЗрдВ рд╕рд╣реЗрдЬрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ рд╕реЗрд╡рд╛рдПрдВ рдФрд░ ViewModel рдХреЗрд╡рд▓ рд╕рд╛рджреЗ рд╡рд╕реНрддреБрдУрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВред
protocol Translatable { associatedtype ManagedObject: Object init(object: ManagedObject) func toManagedObject() -> ManagedObject }
рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рд╕рд╣реЗрдЬрдиреЗ, рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдФрд░ рд╣рдЯрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ рдЕрд▓рдЧ рдЗрдХрд╛рдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ - рднрдВрдбрд╛рд░рдгред рдЪреВрдВрдХрд┐ рд╕реНрдЯреЛрд░реЗрдЬ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рджреНрд╡рд╛рд░рд╛ рдмрдВрдж рд╣реИ, рд╣рдо рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкрд░ рдирд┐рд░реНрднрд░ рдирд╣реАрдВ рд╣реИрдВ рдФрд░ рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ, рддреЛ RealD рдХреЛ рдХреЛрд░рдбрд╛рдЯрд╛ рд╕реЗ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВред
protocol StorageProtocol { func cachedObjects<T: Translatable>() -> [T] func object<T: Translatable>(byPrimaryKey key: AnyHashable) -> T? func save<T: Translatable>(objects: [T]) throws func save<T: Translatable>(object: T) throws func delete<T: Translatable>(objects: [T]) throws func delete<T: Translatable>(object: T) throws func deleteAll<T: Translatable>(ofType type: T.Type) throws }
рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рдкреЗрд╢реЗрд╡рд░реЛрдВ рдФрд░ рд╡рд┐рдкрдХреНрд╖ рдХреНрдпрд╛ рд╣реИрдВ?
рдкреНрд░рддреНрдпреЗрдХ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреА рдЕрдкрдиреА рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдВ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╕рдВрдЧреНрд░рд╣реАрдд рдПрдХ рд░рд┐рдпрд▓ рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреЗрд╡рд▓ рдЙрд╕ рд╕реНрдЯреНрд░реАрдо рдХреЗ рдврд╛рдВрдЪреЗ рдХреЗ рднреАрддрд░ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдЗрд╕реЗ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдпрд╣ рдЕрд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИред
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬрдмрдХрд┐ рдпрд╣ рд░реИрдо рдореЗрдВ рд╣реИ, рдФрд░ рдЗрд╕реЗ рдПрдХреНрд╕реЗрд╕ рдХрд░рдиреЗ рд╕реЗ рдХреНрд░реИрд╢ рд╣реЛ рдЬрд╛рдПрдЧрд╛ред рдХреЛрд░ рдбреЗрдЯрд╛ рдореЗрдВ рд╕рдорд╛рди рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдВ рд╣реИрдВред рдЗрд╕рд▓рд┐рдП, рд╣рдо рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рдСрдмреНрдЬреЗрдХреНрдЯ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ, рдЙрдиреНрд╣реЗрдВ рд╕рд╛рджреЗ рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рдЙрдирдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВред
рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рд╕рд╛рде, рдХреЛрдб рдмрдбрд╝рд╛ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдЗрд╕рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдбреЗрдЯрд╛рдмреЗрд╕ рдХреА рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреЗ рдмрд╛рд╡рдЬреВрдж, рд╣рдо рдХреВрд▓ рдЪрд┐рдкреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдЦреЛ рджреЗрддреЗ рд╣реИрдВред CoreData рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ рдПрдХ FetchedResultsController рд╣реИ, рдЬрд╣рд╛рдВ рд╣рдо рд╕рднреА рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐, рд╡рд┐рд▓реЛрдкрди, рдПрдХ рдЗрдХрд╛рдИ рд╕рд░рдгреА рдХреЗ рднреАрддрд░ рдкрд░рд┐рд╡рд░реНрддрди рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рджрд╛рдпрд░реЗ рдореЗрдВ рдПрдХ рд╣реА рддрдВрддреНрд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВред
рдХреЛрд░ рдШрдЯрдХ
рдХреЛрд░ рдШрдЯрдХ рдРрд╕реА рдЗрдХрд╛рдЗрдпрд╛рдБ рд╣реИрдВ рдЬреЛ рдЕрдкрдирд╛ рдПрдХ рдХрд╛рд░реНрдп рдХрд░рддреА рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдорд╛рдирдЪрд┐рддреНрд░рдг, рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд, рдиреЗрдЯрд╡рд░реНрдХ рдЕрдиреБрд░реЛрдз рднреЗрдЬрдирд╛ рдФрд░ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХрд░рдирд╛ред рдкрд┐рдЫрд▓реЗ рдкреИрд░рд╛рдЧреНрд░рд╛рдл рд╕реЗ рднрдВрдбрд╛рд░рдг рдореБрдЦреНрдп рдШрдЯрдХреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд╣реИред
рдкреНрд░реЛрдЯреЛрдХреЙрд▓
рд╣рдо рд╕рдХреНрд░рд┐рдп рд░реВрдк рд╕реЗ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рд╕рднреА рдореБрдЦреНрдп рдШрдЯрдХ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рджреНрд╡рд╛рд░рд╛ рдмрдВрдж рдХрд░ рджрд┐рдП рдЧрдП рд╣реИрдВ, рдФрд░ рдпреВрдирд┐рдЯ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдирдХрд▓реА рдпрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдо рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд▓рдЪреАрд▓рд╛рдкрди рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВред рд╕рднреА рдирд┐рд░реНрднрд░рддрд╛ init рдореЗрдВ рдкрд╛рд░рд┐рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдкреНрд░рддреНрдпреЗрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░рддреЗ рд╕рдордп, рд╣рдо рд╕рдордЭрддреЗ рд╣реИрдВ рдХрд┐ рдХрд┐рд╕ рддрд░рд╣ рдХреА рдирд┐рд░реНрднрд░рддрд╛рдПрдБ рд╣реИрдВ, рдпрд╣ рдЕрдкрдиреЗ рдЕрдВрджрд░ рдХреНрдпрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред
HTTP рдХреНрд▓рд╛рдЗрдВрдЯ
рдПрдХ рдиреЗрдЯрд╡рд░реНрдХ рдЕрдиреБрд░реЛрдз NetworkRequestParams
рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рджреНрд╡рд╛рд░рд╛ рд╡рд░реНрдгрд┐рдд рд╣реИред
protocol NetworkRequestParams { var path: String { get } var method: HTTPMethod { get } var parameters: Parameters { get } var encoding: ParameterEncoding { get } var headers: [String: String]? { get } var defaultHeaders: [String: String]? { get } }
рд╣рдо рдиреЗрдЯрд╡рд░реНрдХ рдЕрдиреБрд░реЛрдзреЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП enum
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рдпрд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:
enum UserNetworkRouter: URLRequestConvertible { case info case update(userJson:[String : Any]) } extension UserNetworkRouter: NetworkRequestParams { var path: String { switch self { case .info: return "/users/profile" case .update: return "/users/update_profile" } } var method: HTTPMethod { switch self { case .info: return .get case .update: return .post } } var encoding: ParameterEncoding { switch self { case .info: return URLEncoding() case .update: return JSONEncoding() } } var parameters: Parameters { switch self { case .info: return [:] case .update(let userJson): return userJson } } }
рдкреНрд░рддреНрдпреЗрдХ NetworkRouter
URLRequestConvertible
рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЛ рд▓рд╛рдЧреВ URLRequestConvertible
рд╣реИред рд╣рдо рдЗрд╕реЗ рдиреЗрдЯрд╡рд░реНрдХ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рджреЗрддреЗ рд╣реИрдВ, рдЬреЛ рдЗрд╕реЗ URLRequest
рдХрдирд╡рд░реНрдЯ URLRequest
рдФрд░ рдЕрдкрдиреЗ рдЗрдЪреНрдЫрд┐рдд рдЙрджреНрджреЗрд╢реНрдп рдХреЗ рд▓рд┐рдП рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред
рдиреЗрдЯрд╡рд░реНрдХ рдХреНрд▓рд╛рдЗрдВрдЯ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ:
protocol HTTPClientProtocol { func load(request: NetworkRequestParams & URLRequestConvertible) -> SignalProducer<Data, Error> }
рдореИрдкрд░
рд╣рдо рдбреЗрдЯрд╛ рдореИрдкрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП Codable
рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред
protocol MapperProtocol { func map<MappingResult: Codable>(data: Data, dateDecodingStrategy: JSONDecoder.DateDecodingStrategy) -> SignalProducer<MappingResult, Error> }
рд╕реВрдЪрдирд╛рдПрдВ рдкреБрд╢ рдХрд░реЗрдВ
рдкреНрд░рддреНрдпреЗрдХ рдкреБрд╢ рдЕрдзрд┐рд╕реВрдЪрдирд╛ рдореЗрдВ рдПрдХ рдкреНрд░рдХрд╛рд░ рд╣реЛрддрд╛ рд╣реИ рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЕрдкрдирд╛ рд╣реИрдВрдбрд▓рд░ рд╣реЛрддрд╛ рд╣реИред рд╣реИрдВрдбрд▓рд░ рдЕрдзрд┐рд╕реВрдЪрдирд╛ рд╕реЗ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд╕рд╛рде рдПрдХ рд╢рдмреНрджрдХреЛрд╢ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИред рдПрдХрддреНрд░реАрдХрд░рдг рдЗрдХрд╛рдИ рд╕рдВрдЪрд╛рд▓рдХреЛрдВ рдХреЛ рд░рдЦрддреА рд╣реИ, рд╡рд╣ рд╡рд╣ рд╣реИ рдЬреЛ рдзрдХреНрдХрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдЧрд╛ рдФрд░ рдЗрд╕реЗ рд╡рд╛рдВрдЫрд┐рдд рд╣реИрдВрдбрд▓рд░ рдХреЛ рдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд░реЗрдЧрд╛ред рдпрд╣ рдПрдХ рдХрд╛рдлреА рд╕реНрдХреЗрд▓реЗрдмрд▓ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╣реИ рдЬреЛ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ рдЕрдЧрд░ рдЖрдкрдХреЛ рдХрдИ рдкреНрд░рдХрд╛рд░ рдХреЗ рдкреБрд╢ рдиреЛрдЯрд┐рдлрд┐рдХреЗрд╢рди рдХреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рддрд░реАрдХреЗ рд╕реЗ рд╕рдВрднрд╛рд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рд╕реЗрд╡рд╛рдПрдВ
рдореЛрдЯреЗ рддреМрд░ рдкрд░, рдПрдХ рдЗрдХрд╛рдИ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реЗрд╡рд╛ рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИред рдПрдХ рд╕рд╛рдорд╛рдЬрд┐рдХ рдиреЗрдЯрд╡рд░реНрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рд╛рде рдЗрд╕ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХрд╛ рдПрдХ рд╕рд░реНрд╡рд░ рд╣реИ рдЬреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ - рд╕реНрд╡рдпрдВ, рдФрд░ рдпрджрд┐ рд╣рдо рдЗрд╕реЗ рд╕рдВрдкрд╛рджрд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рд╕рдВрд╕реНрдерд╛рдПрдВ рджреЗрддрд╛ рд╣реИред рдПрдХ рдкреЛрд╕реНрдЯ рд╕реЗрд╡рд╛ рд╣реИ рдЬреЛ рдкрджреЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА, рдПрдХ рд╡рд┐рд╕реНрддреГрдд рдкреЛрд╕реНрдЯ, рдПрдХ рднреБрдЧрддрд╛рди рд╕реЗрд╡рд╛ рдЖрджрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреА рд╣реИред рдЖрджрд┐
рд╕рднреА рд╕реЗрд╡рд╛рдУрдВ рдореЗрдВ рдореБрдЦреНрдп рдШрдЯрдХ рд╣реЛрддреЗ рд╣реИрдВред рдЬрдм рд╣рдо рдХрд┐рд╕реА рд╕реЗрд╡рд╛ рдкрд░ рдПрдХ рд╡рд┐рдзрд┐ рдХрд╣рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдореБрдЦреНрдп рдШрдЯрдХреЛрдВ рдХреЗ рд╡рд┐рднрд┐рдиреНрди рддрд░реАрдХреЛрдВ рдХреЛ рдЫреЛрдбрд╝рдирд╛ рд╢реБрд░реВ рдХрд░ рджреЗрддреА рд╣реИ рдФрд░ рдЕрдВрддрддрдГ рдкрд░рд┐рдгрд╛рдо рджреЗрддреА рд╣реИред
рдПрдХ рд╕реЗрд╡рд╛, рдПрдХ рдирд┐рдпрдо рдХреЗ рд░реВрдк рдореЗрдВ, рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕реНрдХреНрд░реАрди рдХреЗ рд▓рд┐рдП рдпрд╛ рд╕реНрдХреНрд░реАрди рд╡реНрдпреВ рдореЙрдбрд▓ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддреА рд╣реИ (рдиреАрдЪреЗ рдЗрд╕ рдкрд░ рдЕрдзрд┐рдХ)ред рдпрджрд┐, рд╕реНрдХреНрд░реАрди рдХреЛ рдЫреЛрдбрд╝рддреЗ рд╕рдордп, рд╕реЗрд╡рд╛ рдирд╖реНрдЯ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИ, рд▓реЗрдХрд┐рди рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЕрдирд╛рд╡рд╢реНрдпрдХ рдиреЗрдЯрд╡рд░реНрдХ рдЕрдиреБрд░реЛрдз рдХреЛ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд╛рд░реА рд╣реИ рдФрд░ рдЕрдиреНрдп рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рдзреАрдорд╛ рдХрд░ рджреЗрдЧрд╛ред рдЗрд╕реЗ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдРрд╕реА рдкреНрд░рдгрд╛рд▓реА рдХреЛ рдмрдирд╛рдП рд░рдЦрдирд╛ рдЕрдзрд┐рдХ рдХрдард┐рди рд╣реЛрдЧрд╛ред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдореЗрдВ рдПрдХ рд╢реВрдиреНрдп рд╣реИ: рдЕрдЧрд░ рд╕реНрдХреНрд░реАрди рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд▓рдиреЗ рдХреЗ рдмрд╛рдж рднреА рд╕реЗрд╡рд╛ рдХреЗ рдкрд░рд┐рдгрд╛рдо рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рддреЛ рдЖрдкрдХреЛ рдЕрдиреНрдп рд╕рдорд╛рдзрд╛рдиреЛрдВ рдХреА рддрд▓рд╛рд╢ рдХрд░рдиреА рд╣реЛрдЧреА, рд╢рд╛рдпрдж рдХреБрдЫ рд╕реЗрд╡рд╛рдУрдВ рдХреЛ рд╕рд┐рдВрдЧрд▓рдЯрди рдмрдирд╛ рджреЗрдВред
рд╕реЗрд╡рд╛рдПрдВ рд╕реНрдЯреЗрдЯрд▓реЗрд╕ рд╣реИрдВред рдЪреВрдВрдХрд┐ рд╕реЗрд╡рд╛рдПрдБ рдПрдХрд▓ рдирд╣реАрдВ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рд╣реА рд╕реЗрд╡рд╛ рдХреЗ рдХрдИ рдЙрджрд╛рд╣рд░рдг рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдореЗрдВ рд░рд╛рдЬреНрдп рдПрдХ рджреВрд╕рд░реЗ рд╕реЗ рднрд┐рдиреНрди рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕рд╕реЗ рдЧрд▓рдд рд╡реНрдпрд╡рд╣рд╛рд░ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред
рд╕реЗрд╡рд╛рдУрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдХреА рдПрдХ рд╡рд┐рдзрд┐ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг:
func currentUser() -> SignalProducer<User, Error> { let request = UserNetworkRouter.info return httpClient.load(request: request) .flatMap(.latest, mapUser) .flatMap(.latest, save) }
ViewModel
рд╣рдо ViewModel рдХреЛ 2 рдкреНрд░рдХрд╛рд░реЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░реЗрдВрдЧреЗ:
- рд╕реНрдХреНрд░реАрди рдХреЗ рд▓рд┐рдП ViewModel (ViewController)
- UIView рдХреЗ рд▓рд┐рдП ViewModel (рддрд╛рд▓рд┐рдХрд╛ рдХреЛрд╢рд┐рдХрд╛рдУрдВ рдпрд╛ UICollectionView рд╕рд╣рд┐рдд)
ViewController рдХреЗ рд▓рд┐рдП ViewModel рд╕реНрдХреНрд░реАрди рдХреЗ рддрд░реНрдХ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИред рдПрдХ рдирд┐рдпрдо рдХреЗ рд░реВрдк рдореЗрдВ, рдпрд╣ рдиреЗрдЯрд╡рд░реНрдХ рдЕрдиреБрд░реЛрдз рднреЗрдЬ рд░рд╣рд╛ рд╣реИ, рдбреЗрдЯрд╛ рддреИрдпрд╛рд░ рдХрд░ рд░рд╣рд╛ рд╣реИ, рдпреВрдЖрдИ рдШрдЯрдирд╛рдУрдВ рдХрд╛ рдЬрд╡рд╛рдм рджреЗ рд░рд╣рд╛ рд╣реИред
ViewModel рд╕реЗрд╡рд╛ рд╕реЗ рдЖрдП рджреГрд╢реНрдп рдХреЗ рд▓рд┐рдП рд╕рднреА рдбреЗрдЯрд╛ рддреИрдпрд╛рд░ рдХрд░рддрд╛ рд╣реИред рдпрджрд┐ рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреА рд╕реВрдЪреА рдЖрддреА рд╣реИ, рддреЛ ViewModel рдЗрд╕реЗ ViewModel рдХреА рд╕реВрдЪреА рдореЗрдВ рдмрджрд▓ рджреЗрддрд╛ рд╣реИ рдФрд░ рдЙрдиреНрд╣реЗрдВ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╛рдзреНрдп рдХрд░рддрд╛ рд╣реИред рдпрджрд┐ рд░рд╛рдЬреНрдп рд╣реИрдВ (рдХреЛрдИ рдЪреЗрдХрдорд╛рд░реНрдХ / рдХреЛрдИ рдЪреЗрдХрдорд╛рд░реНрдХ рдирд╣реАрдВ рд╣реИ), рддреЛ рдпрд╣ рднреА рдкреНрд░рдмрдВрдзрд┐рдд рдФрд░ ViewModel рдХреЛ рдкрд╛рд░рд┐рдд рдХрд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
ViewModel рдиреЗрд╡рд┐рдЧреЗрд╢рди рд▓реЙрдЬрд┐рдХ рдХреЛ рднреА рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рддрд╛ рд╣реИред рдиреЗрд╡рд┐рдЧреЗрд╢рди рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрд▓рдЧ рд░рд╛рдЙрдЯрд░ рдкрд░рдд рд╣реИ, рд▓реЗрдХрд┐рди рд╡реНрдпреВрдореЙрдбрд▓ рдХрдорд╛рдВрдб рджреЗрддрд╛ рд╣реИред
рджреГрд╢реНрдп рдореЙрдбрд▓ рдХреЗ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХрд╛рд░реНрдп: рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реЗрд╡рд╛ рд╕реЗ рд╕рдВрдкрд░реНрдХ рдХрд░реЗрдВ, рдкреНрд░рд╛рдкреНрдд рдореВрд▓реНрдп рд╕реЗ ViewModel рдмрдирд╛рдПрдВред рдЬрдм рд╕рдм рдХреБрдЫ рд▓реЛрдб рд╣реЛрддрд╛ рд╣реИ, рддреЛ ViewModel рд▓реЗрддрд╛ рд╣реИ рдФрд░ рд╡реНрдпреВ рд╕реЗрд▓ рдЦреАрдВрдЪрддрд╛ рд╣реИред
рд╕реНрдХреНрд░реАрди рдХреЗ рд▓рд┐рдП ViewModel рд╕реЗрд╡рд╛рдУрдВ рджреНрд╡рд╛рд░рд╛ рд╕рдорд╛рди рдХрд╛рд░рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рджреНрд╡рд╛рд░рд╛ рдмрдВрдж рдХрд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдПрдХ рдФрд░ рджрд┐рд▓рдЪрд╕реНрдк рдорд╛рдорд▓рд╛ рд╣реИ: рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рдмреИрдВрдХрд┐рдВрдЧ рдПрдкреНрд▓рд┐рдХреЗрд╢рди, рдЬрд╣рд╛рдВ рдкреНрд░рддреНрдпреЗрдХ рдПрдХреНрд╢рди (рдлрдВрдб рдЯреНрд░рд╛рдВрд╕рдлрд░ рдХрд░рдирд╛, рдЦрд╛рддрд╛ рдЦреЛрд▓рдирд╛, рдЕрдХрд╛рдЙрдВрдЯ рдмреНрд▓реЙрдХ рдХрд░рдирд╛) рдПрд╕рдПрдордПрд╕ рджреНрд╡рд╛рд░рд╛ рдкреБрд╖реНрдЯрд┐ рдХреА рдЬрд╛рддреА рд╣реИред рдкреБрд╖реНрдЯрд┐рдХрд░рдг рд╕реНрдХреНрд░реАрди рдкрд░ рдПрдХ рдХреЛрдб рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдлрд╝реАрд▓реНрдб рдФрд░ "рдлрд┐рд░ рд╕реЗ рднреЗрдЬреЗрдВ" рдмрдЯрди рд╣реИред
ViewModel рдЗрд╕ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рджреНрд╡рд╛рд░рд╛ рдмрдВрдж рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
protocol CodeInputViewModelProtocol {
ViewController рдореЗрдВ, рдЗрд╕реЗ рдирд┐рдореНрди рд░реВрдк рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:
var viewModel: CodeInputViewModelProtocol?
рдПрд╕рдПрдордПрд╕ рджреНрд╡рд╛рд░рд╛ рдкреБрд╖реНрдЯрд┐ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдо рдХреНрдпрд╛ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рдЗрд╕ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддреЗ рд╣реБрдП, рдПрдХ рдХреЛрдб рднреЗрдЬрдирд╛ рдФрд░ рдПрд╕рдПрдордПрд╕ рднреЗрдЬрдирд╛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдЕрдиреБрд░реЛрдзреЛрдВ рджреНрд╡рд╛рд░рд╛ рджрд░реНрд╢рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рдкреБрд╖реНрдЯрд┐ рдХреЗ рдмрд╛рдж, рд╡рд┐рднрд┐рдиреНрди рд╕реНрдХреНрд░реАрди рдкрд░ рд╕рдВрдХреНрд░рдордг рдЖрджрд┐ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдЪреВрдВрдХрд┐ ViewController рдкрд░рд╡рд╛рд╣ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдХрд┐рд╕ рдкреНрд░рдХрд╛рд░ рдХрд╛ ViewModel рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╣реИ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╡рд┐рднрд┐рдиреНрди рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП рдХрдИ ViewModel рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ UI рд╕рд╛рдорд╛рдиреНрдп рд╣реЛрдЧрд╛ред
ViewModel рд╡реНрдпреВ рдФрд░ рдХреЛрд╢рд┐рдХрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдЖрдорддреМрд░ рдкрд░ рдбреЗрдЯрд╛ рд╕реНрд╡рд░реВрдкрдг рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдирдкреБрдЯ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЪрдпрдирд┐рдд / рдЪрдпрдирд┐рдд рд░рд╛рдЬреНрдп рдХрд╛ рднрдВрдбрд╛рд░рдг рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред
final class FeedCellViewModel { let url: URL? let title: String let subtitle: String init(feed: FeedItem) { url = URL(string: feed.imageUrl) title = feed.title subtitle = DateFormatter.feed.string(from feed.publishDate) } }
рдиреЗрд╡рд┐рдЧреЗрд╢рди
рд░рд╛рдЙрдЯрд░ рджреНрд╡рд╛рд░рд╛ рд╕реНрдХреНрд░реАрди рдХреЗ рдмреАрдЪ рд╕рдВрдХреНрд░рдордг рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
class BaseRouter { init(sourceViewController: UIViewController) { self.sourceViewController = sourceViewController } weak var sourceViewController: UIViewController? }
рдкреНрд░рддреНрдпреЗрдХ рд╕реНрдХреНрд░реАрди рдХрд╛ рдЕрдкрдирд╛ рд░рд╛рдЙрдЯрд░ рд╣реЛрддрд╛ рд╣реИ, рдЬреЛ рдЖрдзрд╛рд░ рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓рд╛ рд╣реИред рдЗрд╕рдореЗрдВ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕реНрдХреНрд░реАрди рдХреЗ рд▓рд┐рдП рд╕рдВрдХреНрд░рдордг рдХреЗ рддрд░реАрдХреЗ рд╣реИрдВред
final class FeedRouter : BaseRouter { func showDetail(viewModel: FeedDetailViewModelProtocol) { let vc = FeedDetailViewController() vc.viewModel = viewModel sourceViewController?.navigationController?.pushViewController(vc, animated: true) } }
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдКрдкрд░ рджрд┐рдП рдЧрдП рдЙрджрд╛рд╣рд░рдг рд╕реЗ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рд░рд╛рдЙрдЯрд░ рдореЗрдВ "рдореЙрдбреНрдпреВрд▓" рдХреА рдЕрд╕реЗрдВрдмрд▓реА рд╣реЛрддреА рд╣реИред рдпрд╣ рдФрдкрдЪрд╛рд░рд┐рдХ рд░реВрдк рд╕реЗ рдПрд╕ рдХреЛ рдПрд╕рдУрдПрд▓рдЖрдИрдбреА рд╕реЗ рдкрддреНрд░ рдХрд╛ рдЦрдВрдбрди рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╡реНрдпрд╡рд╣рд╛рд░ рдореЗрдВ рдпрд╣ рдХрд╛рдлреА рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ рдФрд░ рд╕рдорд╕реНрдпрд╛рдУрдВ рдХрд╛ рдХрд╛рд░рдг рдирд╣реАрдВ рд╣реИред
рдХрдИ рдмрд╛рд░ рдЕрд▓рдЧ-рдЕрд▓рдЧ рд░рд╛рдЙрдЯрд░ рдореЗрдВ рдПрдХ рд╣реА рд╡рд┐рдзрд┐ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдЗрд╕реЗ рдХрдИ рдмрд╛рд░ рдирд╣реАрдВ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдмрдирд╛рддреЗ рд╣реИрдВ рдЬрд┐рд╕рдореЗрдВ рд╕рд╛рдорд╛рдиреНрдп рддрд░реАрдХреЗ рд╣реЛрдВрдЧреЗ, рдФрд░ рд╣рдо рдЗрд╕реЗ extension
рд▓рд╛рдЧреВ рдХрд░реЗрдВрдЧреЗред рдЕрдм рдЗрд╕ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЗ рд▓рд┐рдП рд╡рд╛рдВрдЫрд┐рдд рд░рд╛рдЙрдЯрд░ рдкрд░ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдХрд░рдирд╛ рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ, рдФрд░ рдЗрд╕рдореЗрдВ рдЖрд╡рд╢реНрдпрдХ рддрд░реАрдХреЗ рд╣реЛрдВрдЧреЗред
protocol FeedRouterProtocol { func showDetail(viewModel: FeedDetailViewModelProtocol) } extension FeedRouterProtocol where Self: BaseRouter { func showDetail(viewModel: FeedDetailViewModelProtocol) { let vc = FeedDetailViewController() vc.viewModel = viewModel sourceViewController?.navigationController?.pushViewController(vc, animated: true) } }
рд░рд╛рдп
рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд╛рд░рдВрдкрд░рд┐рдХ рд░реВрдк рд╕реЗ рджреГрд╢реНрдп рдкрд╛рд░рдВрдкрд░рд┐рдХ рд░реВрдк рд╕реЗ рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИред MVVM рдореЗрдВ, рд╣рдореЗрдВ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ ViewController рдПрдХ рджреГрд╢реНрдп рд╣реИред рдпрд╣ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдХрд┐ рдХреЛрдИ рднреА рдЬрдЯрд┐рд▓ рддрд░реНрдХ рди рд╣реЛ рдЬрд┐рд╕реЗ рд╡реНрдпреВрдореЙрдбрд▓ рдореЗрдВ рдЬрдЧрд╣ рдорд┐рд▓реЗред рдХрд┐рд╕реА рднреА рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдПрдорд╡реАрд╕реА рдореЗрдВ, рдЖрдкрдХреЛ рд╡реНрдпреВрдХрдВрдЯреНрд░реЛрд▓рд░ рдХреЛ рднрд╛рд░реА рд░реВрдк рд╕реЗ рд▓реЛрдб рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдРрд╕рд╛ рдХрд░рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реИред
ViewModel рдХреЛ рдХрдорд╛рдВрдб рджреЗрдЦреЗрдВред рдпрджрд┐ ViewController рд▓реЛрдб рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рддреЛ рд╣рдо ViewModel рдХрдорд╛рдВрдб рджреЗрддреЗ рд╣реИрдВ: рдиреЗрдЯрд╡рд░реНрдХ рд╕реЗ рдпрд╛ рдХреИрд╢ рд╕реЗ рдбреЗрдЯрд╛ рд▓реЛрдб рдХрд░реЗрдВред рд╡реНрдпреВ рднреА ViewModel рд╕реЗ рд╕рдВрдХреЗрддреЛрдВ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИред рдпрджрд┐ ViewModel рдХрд╣рддрд╛ рд╣реИ рдХрд┐ рдХреБрдЫ рдмрджрд▓ рдЧрдпрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдмрд╣реБрдд рдбреЗрдЯрд╛ рд▓реЛрдб рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ), рддреЛ View рдЗрд╕ рдкрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдлрд┐рд░ рд╕реЗ рдмрддрд╛рддрд╛ рд╣реИред
рд╣рдо рд╕реНрдЯреЛрд░реАрдмреЛрд░реНрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред рдиреЗрд╡рд┐рдЧреЗрд╢рди, рд╡реНрдпреВ рдХреЙрдиреНрдЯреНрд░реЛрд▓рд░ рд╕реЗ рдмрд╣реБрдд рдЕрдзрд┐рдХ рдЬреБрдбрд╝рд╛ рд╣реБрдЖ рд╣реИ, рдФрд░ рдпрд╣ рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдореЗрдВ рдлрд┐рдЯ рд╣реЛрдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реИред рд╕реНрдЯреЛрд░реАрдмреЛрд░реНрдбреНрд╕ рдореЗрдВ рдЕрдХреНрд╕рд░ рдЯрдХрд░рд╛рд╡ рдкреИрджрд╛ рд╣реЛрддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рд╕рдВрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрд▓рдЧ "рдЖрдирдВрдж" рд╣реИред
рдЖрдЧреЗ рдХреНрдпрд╛ рдХрд░рдирд╛ рд╣реИ?
рдЖрдк рдореЙрдбрд▓ (рдЯреНрд░рд╛рдВрд╕рд▓реЗрдЯреЗрдмрд▓) рдХреЗ рд▓рд┐рдП рдХреЛрдб рдЬрдирд░реЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рдбреЗрдЯрд╛рдмреЗрд╕ рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реЗ рдкреНрд▓рд╛рди рдСрдмреНрдЬреЗрдХреНрдЯ рддрдХ рд╕рднреА рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝реЗрд╢рди рдФрд░ рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрдд рдЕрдм рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдкрдВрдЬреАрдХреГрдд рд╣реИрдВред
рдЖрдк рдПрдХ рдЕрдзрд┐рдХ рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рдХреНрд╡реЗрд░реА рдпреЛрдЬрдирд╛ рдХрд╛ рднреА рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рд╕реЗрд╡рд╛рдУрдВ рдХреЗ рдХрдИ рддрд░реАрдХреЗ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддреЗ рд╣реИрдВ: рдиреЗрдЯрд╡рд░реНрдХ рдкрд░ рдЬрд╛рдПрдВ, рдореИрдкрд┐рдВрдЧ рд▓рд╛рдЧреВ рдХрд░реЗрдВ, рдбреЗрдЯрд╛рдмреЗрд╕ рдкрд░ рд╕рд╣реЗрдЬреЗрдВред рдпрд╣ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдХрдВрдХрд╛рд▓ рд╕реЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рднреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИред
рд╣рдордиреЗ рд╡рд╛рд╕реНрддреБрд╢рд┐рд▓реНрдк рджреГрд╖реНрдЯрд┐рдХреЛрдг рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд┐рдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдордд рднреВрд▓реЛ рдХрд┐ рдПрдХ рдЙрдЪреНрдЪ-рдЧреБрдгрд╡рддреНрддрд╛ рд╡рд╛рд▓рд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рди рдХреЗрд╡рд▓ рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рд╣реИ, рдмрд▓реНрдХрд┐ рдПрдХ рдЪрд┐рдХрдиреА, рдЙрддреНрддрд░рджрд╛рдпреА, рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рднреА рд╣реИред рдЕрдкрдиреЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рд╕реЗ рдкреНрдпрд╛рд░ рдХрд░реЗрдВ рдФрд░ рдХреНрд╡рд╛рд▓рд┐рдЯреА рдРрдкреНрд╕ рд▓рд┐рдЦреЗрдВред