UICollectionViewCell рдХрд╛ рдирд┐рд╕реНрддрд╛рд░рдг рдХрд░рдирд╛

рдХреАрдиреЛрдЯ WWDC 2019 рдХреЛ рджреЗрдЦрдиреЗ рдХреЗ рдмрд╛рдж рдФрд░ SwiftUI рдХреЛ рдЬрд╛рдирдиреЗ рдХреЗ рд▓рд┐рдП, рдЬреЛ рдХрд┐ рдХреЛрдб рдореЗрдВ UIs рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдореИрдВ рдЗрд╕ рдмрд╛рдд рдкрд░ рдЕрдЯрдХрд▓ рд▓рдЧрд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдкреНрд▓реЗрдЯ рдФрд░ рд╕рдВрдЧреНрд░рд╣ рдореЗрдВ рдШреЛрд╖рдгрд╛рддреНрдордХ рд░реВрдк рд╕реЗ рдХреИрд╕реЗ рднрд░реЗрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЗрд╕ рддрд░рд╣:


enum Builder { static func widgets(objects: Objects) -> [Widget] { let header = [ Spacing(height: 25).widget, Header(string: " ").widget, Spacing(height: 10, separator: .bottom).widget ] let body = objects .flatMap({ (object: Object) -> [Widgets] in return [ Title(object: object).widget, Spacing(height: 1, separator: .bottom).widget ] }) return header + body } } let objects: [Object] = ... Builder .widgets(objects: objects) .bind(to: collectionView) 

рд╕рдВрдЧреНрд░рд╣ рдореЗрдВ, рдЗрд╕реЗ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:

рдЫрд╡рд┐


рдкрд░рд┐рдЪрдп


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


рд╕реЗрд▓ рдЕрдкрдШрдЯрди рдХрд╛ рдЕрд░реНрде рд╣реИ рдПрдХ рдХреЛрд╢рд┐рдХрд╛ рдХреЛ рдХрдИ рдЫреЛрдЯреА рдХреЛрд╢рд┐рдХрд╛рдУрдВ рдХреЗ рд╕рд╛рде рдмрджрд▓рдирд╛ред рдЗрд╕ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдХреЗ рд╕рд╛рде, рдиреЗрддреНрд░рд╣реАрди рдХреБрдЫ рднреА рдирд╣реАрдВ рдмрджрд▓рдирд╛ рдЪрд╛рд╣рд┐рдПред рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ, iOS рдХреЗ рд▓рд┐рдП VK рд╕рдорд╛рдЪрд╛рд░ рдлрд╝реАрдб рд╕реЗ рдкреЛрд╕реНрдЯ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред рдПрдХ рдкреЛрд╕реНрдЯ рдХреЛ рдПрдХрд▓ рдХреЛрд╢рд┐рдХрд╛, рдпрд╛ рдХреЛрд╢рд┐рдХрд╛рдУрдВ рдХреЗ рд╕рдореВрд╣ рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ - рдЖрджрд┐рдо ред


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


рдкреЗрд╢реЗрд╡рд░реЛрдВ рдФрд░ рд╡рд┐рдкрдХреНрд╖


рдХреЛрд╢рд┐рдХрд╛рдУрдВ рдХреЗ рдЕрдкрдШрдЯрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рддрд╛рд▓рд┐рдХрд╛рдУрдВ / рд╕рдВрдЧреНрд░рд╣реЛрдВ рдореЗрдВ рдкреНрд░рд╛рдпрдорд┐рдХреНрд╕ рд╢рд╛рдорд┐рд▓ рд╣реЛрддреЗ рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рдЕрдХреНрд╕рд░ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛: рдкрд╛рда рдХреЗ рд╕рд╛рде рдПрдХ рдЖрджрд┐рдо, рдЪрд┐рддреНрд░ рдХреЗ рд╕рд╛рде рдПрдХ рдЖрджрд┐рдо, рдПрдХ рдкреГрд╖реНрдарднреВрдорд┐ рдХреЗ рд╕рд╛рде рдПрдХ рдЖрджрд┐рдоред рдПрдХ рдПрдХрд▓ рдЖрджрд┐рдо рдХреА рдКрдВрдЪрд╛рдИ рдХреА рдЧрдгрдирд╛ рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рд░рд╛рдЬреНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдЬрдЯрд┐рд▓ рд╕реЗрд▓ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдмрд╣реБрдд рд╕рд░рд▓ рдФрд░ рдЕрдзрд┐рдХ рдкреНрд░рднрд╛рд╡реА рд╣реИред рдпрджрд┐ рд╡рд╛рдВрдЫрд┐рдд рд╣реИ, рддреЛ рдЖрджрд┐рдо рдХреА рдЧрддрд┐рд╢реАрд▓ рдКрдВрдЪрд╛рдИ рдХреА рдЧрдгрдирд╛ рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИ рдпрд╛ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдкреГрд╖реНрдарднреВрдорд┐ рдореЗрдВ рдЦреАрдВрдЪреА рдЬрд╛ рд╕рдХрддреА рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, CTFramesetter рдорд╛рдзреНрдпрдо рд╕реЗ рдкрд╛рда)ред


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


рдЖрдк рдЗрд╕ рдЙрджреНрдпрдо рдХреЗ рд╕рдВрднрд╛рд╡рд┐рдд рдкреЗрд╢реЗрд╡рд░реЛрдВ рдФрд░ рд╡рд┐рдкрдХреНрд╖реЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рдмрд╛рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╕реЗрд▓ рдЕрдкрдШрдЯрди рдХреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рдирд╛ рдмреЗрд╣рддрд░ рд╣реИред


рдЙрдкрдХрд░рдг рдЪреБрдирдирд╛


рдЪреВрдВрдХрд┐ UITableView рдЕрдкрдиреА рдХреНрд╖рдорддрд╛рдУрдВ рдореЗрдВ рд╕реАрдорд┐рдд рд╣реИ, рдФрд░, рдЬреИрд╕рд╛ рдХрд┐ рдкрд╣рд▓реЗ рд╣реА рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЬрдЯрд┐рд▓ рдкреНрд▓реЗрдЯ рд╣реИрдВ, UICollectionView рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЙрдкрдпреБрдХреНрдд рд╕рдорд╛рдзрд╛рди рд╣реЛрдЧрд╛ред рдпрд╣ UICollectionView рдмрд╛рд░реЗ рдореЗрдВ рд╣реИ UICollectionView рдЗрд╕ рдкреНрд░рдХрд╛рд╢рди рдореЗрдВ рдЪрд░реНрдЪрд╛ рдХреА рдЬрд╛рдПрдЧреАред


UICollectionView рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ UICollectionView рдПрдХ рдРрд╕реА рд╕реНрдерд┐рддрд┐ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝рддрд╛ рд╣реИ, рдЬрд╣рд╛рдВ рдЖрдзрд╛рд░ UICollectionViewFlowLayout рд╕рдВрдЧреНрд░рд╣ рдХреЗ рддрддреНрд╡реЛрдВ рдХреА рд╡рд╛рдВрдЫрд┐рдд рд╡реНрдпрд╡рд╕реНрдерд╛ рдирд╣реАрдВ UICollectionViewFlowLayout рд╕рдХрддрд╛ рд╣реИ (рд╣рдо рдирдП UICollectionViewCompositionalLayout рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рдирд╣реАрдВ UICollectionViewCompositionalLayout )ред рдРрд╕реЗ рдХреНрд╖рдгреЛрдВ рдореЗрдВ, рдирд┐рд░реНрдгрдп рдЖрдорддреМрд░ рдкрд░ рдХреБрдЫ рдУрдкрди-рд╕реЛрд░реНрд╕ UICollectionViewLayout рдХреЛ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рддреИрдпрд╛рд░ рдХрд┐рдП рдЧрдП рд╕рдорд╛рдзрд╛рдиреЛрдВ рдХреЗ рдмреАрдЪ рднреА, рдПрдХ рдЙрдкрдпреБрдХреНрдд рдПрдХ рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рдмрдбрд╝реЗ рдСрдирд▓рд╛рдЗрди рд╕реНрдЯреЛрд░ рдпрд╛ рд╕рд╛рдорд╛рдЬрд┐рдХ рдиреЗрдЯрд╡рд░реНрдХ рдХреЗ рдЧрддрд┐рд╢реАрд▓ рдореБрдЦреНрдп рдкреГрд╖реНрда рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВред рд╣рдо рд╕рдмрд╕реЗ рдЦрд░рд╛рдм рдорд╛рдирддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЕрдкрдирд╛ рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ UICollectionViewLayout ред


рд▓реЗрдЖрдЙрдЯ рдЪреБрдирдиреЗ рдореЗрдВ рдХрдард┐рдирд╛рдИ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЖрдкрдХреЛ рдпрд╣ рддрдп рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рд╕рдВрдЧреНрд░рд╣ рдбреЗрдЯрд╛ рдХреИрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдЧрд╛ред рд╕рд╛рдорд╛рдиреНрдп рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЬрд╣рд╛рдВ рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ (рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдмрд╛рд░ рдПрдХ UIViewController ) UICollectionViewDataSource рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХрд╛ рдЕрдиреБрдкрд╛рд▓рди рдХрд░рддрд╛ рд╣реИ рдФрд░ рдПрдХ рд╕рдВрдЧреНрд░рд╣ рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ, рдбреЗрдЯрд╛-рд╕рдВрдЪрд╛рд▓рд┐рдд рдлреНрд░реЗрдорд╡рд░реНрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рд▓реЛрдХрдкреНрд░рд┐рдпрддрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд░рд╣рд╛ рд╣реИред рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рдЙрдЬреНрдЬреНрд╡рд▓ рдкреНрд░рддрд┐рдирд┐рдзрд┐ CollectionKit , IGListKit , RxDataSources, рдФрд░ рдЕрдиреНрдп рд╣реИрдВред рдЗрд╕ рддрд░рд╣ рдХреЗ рдврд╛рдВрдЪреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╕рдВрдЧреНрд░рд╣ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХреЛ рд╕рд░рд▓ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдбреЗрдЯрд╛ рдХреЛ рдЪреЗрддрди рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЕрд▓рдЧ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдврд╛рдВрдЪреЗ рдореЗрдВ рдореМрдЬреВрдж рд╣реИред рдкреНрд░рдХрд╛рд╢рди рдХреЗ рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП, RxDataSource рдврд╛рдВрдЪреЗ рдХрд╛ рдЪрдпрди рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред


рд╡рд┐рдЬреЗрдЯ рдФрд░ рдЙрд╕рдХреЗ рдЧреБрдг


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


  1. рд╡рд┐рдЬреЗрдЯ рдХреЛ рдбреЗрдЯрд╛-рд╕рдВрдЪрд╛рд▓рд┐рдд рдврд╛рдВрдЪреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХрд╛ рдкрд╛рд▓рди рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЗрд╕ рддрд░рд╣ рдХреЗ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдореЗрдВ рдЖрдорддреМрд░ рдкрд░ рдПрдХ рд╕рдВрдмрджреНрдз рдорд╛рди рд╣реЛрддрд╛ рд╣реИ (рдЬреИрд╕реЗ RxDataSources рдореЗрдВ IdentifiableType рдЯрд╛рдЗрдк )
  2. рдХрд┐рд╕реА рд╕рд░рдгреА рдореЗрдВ рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рд╛рдЗрдореЗрдЯ рдХреЗ рд▓рд┐рдП рд╡рд┐рдЬреЗрдЯреНрд╕ рдХреЛ рдЗрдХрдЯреНрдард╛ рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдЗрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╡рд┐рдЬреЗрдЯ рдореЗрдВ рд╕рдВрдмрдВрдзрд┐рдд рдореВрд▓реНрдп рдирд╣реАрдВ рд╣реЛрдиреЗ рдЪрд╛рд╣рд┐рдПред рдЗрди рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП, рдЖрдк рдкреНрд░рдХрд╛рд░ рдХреЗ рдХреНрд╖рд░рдг рдХреЗ рддрдВрддреНрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдпрд╛ рдРрд╕рд╛ рдХреБрдЫ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
  3. рд╡рд┐рдЬреЗрдЯ рдЖрджрд┐рдо рдХреЗ рдЖрдХрд╛рд░ рдХреЛ рдЧрд┐рдирдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдлрд┐рд░, UICollectionViewLayout рдмрдирд╛рддреЗ рд╕рдордп, рдпрд╣ рдХреЗрд╡рд▓ рдкреВрд░реНрд╡рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдирд┐рдпрдореЛрдВ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдЖрджрд┐рдо рд╕реНрдерд┐рддрд┐ рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рд░рд╣рддрд╛ рд╣реИред
  4. рд╡рд┐рдЬреЗрдЯ UICollectionViewCell рд▓рд┐рдП рдХрд╛рд░рдЦрд╛рдирд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдЗрд╕рд▓рд┐рдП, UICollectionViewDataSource рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╕реЗ UICollectionViewDataSource рд╕реЗрд▓ рдмрдирд╛рдиреЗ рдХреЗ рд╕рднреА рддрд░реНрдХ рд╣рдЯрд╛ рджрд┐рдП рдЬрд╛рдПрдВрдЧреЗ рдФрд░ рдЬреЛ рдХреБрдЫ рднреА рд╢реЗрд╖ рд╣реИ:
     let cell = widget.widgetCell(collectionView: collectionView, indexPath: indexPath) return cell 

рд╡рд┐рдЬреЗрдЯ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди


RxDataSource рдлреНрд░реЗрдорд╡рд░реНрдХ рдХреЗ рд╕рд╛рде рд╡рд┐рдЬреЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП, рдЗрд╕реЗ Equatable рдФрд░ IdentifiableType Equatable рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХрд╛ рдкрд╛рд▓рди рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП ред рдЪреВрдВрдХрд┐ рд╡рд┐рдЬреЗрдЯ рдПрдХ рдЖрджрд┐рдо рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдкреНрд░рдХрд╛рд╢рди рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реЛрдЧрд╛ рдпрджрд┐ рд╡рд┐рдЬреЗрдЯ рдкрд╣рдЪрд╛рди рдХрд░рдиреЗ IdentifiableType рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЗ рдЕрдиреБрдкрд╛рд▓рди рдХреЗ рд▓рд┐рдП рд╕реНрд╡рдпрдВ рдХреА IdentifiableType рд╣реИред рд╡реНрдпрд╡рд╣рд╛рд░ рдореЗрдВ, рдпрд╣ рдЗрд╕ рддрдереНрдп рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░реЗрдЧрд╛ рдХрд┐ рдЬрдм рд╡рд┐рдЬреЗрдЯ рдмрджрд▓рддрд╛ рд╣реИ, рддреЛ рдЖрджрд┐рдо рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓реЛрдб рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рд▓реЗрдХрд┐рди рд╣рдЯрд╛ рджрд┐рдпрд╛ рдФрд░ рдбрд╛рд▓рд╛ рдЬрд╛рдПрдЧрд╛ред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдирдпрд╛ WidgetIdentifiable рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдкреЗрд╢ рдХрд░реЗрдВ:


 protocol WidgetIdentifiable: IdentifiableType { } extension WidgetIdentifiable { var identity: Self { return self } } 

WidgetIdentifiable рдЕрдиреБрд░реВрдк рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП, рд╡рд┐рдЬреЗрдЯ рдХреЛ WidgetIdentifiable рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЗ рдЕрдиреБрд░реВрдк рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред Hashable рд╡рд┐рдЬреЗрдЯ рдЙрд╕ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рд╕реЗ рдЕрдиреБрдкрд╛рд▓рди рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛ рд▓реЗрдЧрд╛ рдЬреЛ рдХрд┐рд╕реА рд╡рд┐рд╢реЗрд╖ рдЖрджрд┐рдо рдХрд╛ рд╡рд░реНрдгрди рдХрд░реЗрдЧрд╛ред рдЖрдк рдСрдмреНрдЬреЗрдХреНрдЯ рдкреНрд░рдХрд╛рд░ рд╡рд┐рдЬреЗрдЯ рдХреЛ "рдорд┐рдЯрд╛" рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП AnyHashable рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред


 struct Widget: WidgetIdentifiable { let underlying: AnyHashable init(_ underlying: AnyHashable) { self.underlying = underlying } } extension Widget: Hashable { func hash(into hasher: inout Hasher) { self.underlying.hash(into: &hasher) } static func ==(lhs: Widget, rhs: Widget) -> Bool { return lhs.underlying == rhs.underlying } } 

рдЗрд╕ рд╕реНрддрд░ рдкрд░, рд╡рд┐рдЬреЗрдЯ рдХреЗ рдкрд╣рд▓реЗ рджреЛ рдЧреБрдгреЛрдВ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдПрдХ рд╕рд░рдгреА рдореЗрдВ рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рдХрд╛рд░ рдХреА рд╡рд╕реНрддреБрдУрдВ рдХреЗ рд╕рд╛рде рдХрдИ рд╡рд┐рдЬреЗрдЯреНрд╕ рдХреЛ рдЗрдХрдЯреНрдард╛ рдХрд░рдХреЗ рдЬрд╛рдВрдЪрдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рд╣реИред


 let widgets = [Widget("Hello world"), Widget(100500)] 

рд╢реЗрд╖ рдЧреБрдгреЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ рдирдпрд╛ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ WidgetPresentable рдкреЗрд╢ WidgetPresentable


 protocol WidgetPresentable { func widgetCell(collectionView: UICollectionView, indexPath: IndexPath) -> UICollectionViewCell func widgetSize(containerWidth: CGFloat) -> CGSize } 

widgetSize(containerWidth:) рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ UICollectionViewLayout рдореЗрдВ рдХреЛрд╢рд┐рдХрд╛рдУрдВ рдХреЗ рдЧреБрдг рдкреИрджрд╛ рдХрд░рддреЗ рд╕рдордп рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдФрд░ widgetCell(collectionView:indexPath:) - рдХреЛрд╢рд┐рдХрд╛рдУрдВ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред


рдпрджрд┐ рд╡рд┐рдЬреЗрдЯ WidgetPresentable рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЗ WidgetPresentable , рддреЛ рд╡рд┐рдЬреЗрдЯ рдкреНрд░рдХрд╛рд╢рди рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ рд╕рдВрдХреЗрддрд┐рдд рд╕рднреА рдЧреБрдгреЛрдВ рдХреЛ рдкреВрд░рд╛ рдХрд░реЗрдЧрд╛ред рд╣рд╛рд▓рд╛рдБрдХрд┐, рд╡рд┐рдЬреЗрдЯ AnyHashable рдореЗрдВ рдирд┐рд╣рд┐рдд рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ WidgetPresentable рдФрд░ WidgetHashable рд╕рд╛рде WidgetHashable рд╣реЛрдЧрд╛, рдЬрд╣рд╛рдБ WidgetHashable рдХрд╛ рд╕рдВрдмрджреНрдз рдорд╛рди рдирд╣реАрдВ рд╣реЛрдЧрд╛ (рдЬреИрд╕рд╛ рдХрд┐ WidgetHashable рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ) рдФрд░ рд╡рд┐рдЬреЗрдЯ рдХреЗ рдЕрдВрджрд░ рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рдкреНрд░рдХрд╛рд░ "рдорд┐рдЯ" рд░рд╣реЗрдЧрд╛:


 protocol WidgetHashable { func widgetEqual(_ any: Any) -> Bool func widgetHash(into hasher: inout Hasher) } 

рдЕрдВрддрд┐рдо рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ, рд╡рд┐рдЬреЗрдЯ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦреЗрдЧрд╛:


 struct Widget: WidgetIdentifiable { let underlying: WidgetHashable & WidgetPresentable init(_ underlying: WidgetHashable & WidgetPresentable) { self.underlying = underlying } } extension Widget: Hashable { func hash(into hasher: inout Hasher) { self.underlying.widgetHash(into: &hasher) } static func ==(lhs: Widget, rhs: Widget) -> Bool { return lhs.underlying.widgetEqual(rhs.underlying) } } extension Widget: WidgetPresentable { func widgetCell(collectionView: UICollectionView, indexPath: IndexPath) -> UICollectionViewCell { return underlying.widgetCell(collectionView: collectionView, indexPath: indexPath) } func widgetSize(containerWidth: CGFloat) -> CGSize { return underlying.widgetSize(containerWidth: containerWidth) } } 

рдЖрджрд┐рдо рд╡рд╕реНрддреБ


рдЖрдЗрдП рд╕рд░рд▓рддрдо рдЖрджрд┐рдо рдХреЛ рдЗрдХрдЯреНрдард╛ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ, рдЬреЛ рдХрд┐рд╕реА рджрд┐рдП рдЧрдП рдКрдВрдЪрд╛рдИ рдХрд╛ рдЗрдВрдбреЗрдВрдЯреЗрд╢рди рд╣реЛрдЧрд╛ред


 struct Spacing: Hashable { let height: CGFloat } class SpacingView: UIView { lazy var constraint = self.heightAnchor.constraint(equalToConstant: 1) init() { super.init(frame: .zero) self.constraint.isActive = true } } extension Spacing: WidgetHashable { func widgetEqual(_ any: Any) -> Bool { if let spacing = any as? Spacing { return self == spacing } return false } func widgetHash(into hasher: inout Hasher) { self.hash(into: &hasher) } } extension Spacing: WidgetPresentable { func widgetCell(collectionView: UICollectionView, indexPath: IndexPath) -> UICollectionViewCell { let cell: WidgetCell<SpacingView> = collectionView.cellDequeueSafely(indexPath: indexPath) if cell.view == nil { cell.view = SpacingView() } cell.view?.constraint.constant = height return cell } func widgetSize(containerWidth: CGFloat) -> CGSize { return CGSize(width: containerWidth, height: height) } } 

WidgetCell<T> рдХрд╛ рд╕рд┐рд░реНрдл рдПрдХ рдЙрдкрд╡рд░реНрдЧ рд╣реИ рдЬреЛ рдПрдХ UIView рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рдПрдХ UICollectionViewCell рд░реВрдк рдореЗрдВ рдЬреЛрдбрд╝рддрд╛ рд╣реИред cellDequeueSafely(indexPath:) рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд╣реИ рдЬреЛ рд╕рдВрдЧреНрд░рд╣ рдореЗрдВ рдПрдХ рд╕реЗрд▓ рдХреЛ рдлрд┐рд░ рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдкрдВрдЬреАрдХреГрдд рдХрд░рддрд╛ рд╣реИ рдпрджрд┐ рд╕рдВрдЧреНрд░рд╣ рдореЗрдВ рдХреЛрдИ рд╕реЗрд▓ рдкрд╣рд▓реЗ рдкрдВрдЬреАрдХреГрдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдкреНрд░рдХрд╛рд╢рди рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ рд╡рд░реНрдгрд┐рдд Spacing рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред


рд╡рд┐рдЧреЗрдЯреНрд╕ рдХреА рд╕рд░рдгреА рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдпрд╣ рдХреЗрд╡рд▓ observerWidgets рд▓рд┐рдП рдмрд╛рдзреНрдп рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдиреА рд╣реБрдИ рд╣реИ:


 typealias DataSource = RxCollectionViewSectionedAnimatedDataSource<WidgetSection> class Controller: UIViewController { private lazy var dataSource: DataSource = self.makeDataSource() var observerWidgets: (Observable<Widgets>) -> Disposable { return collectionView.rx.items(dataSource: dataSource) } func makeDataSource() -> DataSource { return DataSource(configureCell: { (_, collectionView: UICollectionView, indexPath: IndexPath, widget: Widget) in let cell = widget.widgetCell(collectionView: collectionView, indexPath: indexPath) return cell }) } } 

рдкрд░рд┐рдгрд╛рдо


рдЕрдВрдд рдореЗрдВ, рдореИрдВ рд╕рдВрдЧреНрд░рд╣ рдХрд╛ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдХрд╛рдо рджрд┐рдЦрд╛рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛, рдЬреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╡рд┐рдЧреЗрдЯреНрд╕ рдкрд░ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред


рдЫрд╡рд┐

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


рдЯрд┐рдкреНрдкрдгреА


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


WidgetPresentable рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЛ рдЕрдиреНрдп рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬреЛ рд▓реЗрдЖрдЙрдЯ рдХреЛ рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, widgetSizeEstimated(containerWidth:) рдпрд╛ widgetSizePredefined(containerWidth:) , рдЬреЛ рдХреНрд░рдорд╢рдГ рдЕрдиреБрдорд╛рдирд┐рдд рдФрд░ рдирд┐рд╢реНрдЪрд┐рдд рдЖрдХрд╛рд░ рд▓реМрдЯрд╛рддреЗ рд╣реИрдВред рдпрд╣ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐ widgetSize(containerWidth:) рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдЧрдгрдирд╛ рдХреА рдорд╛рдВрдЧ рдХреЗ рд▓рд┐рдП рднреА рдЖрджрд┐рдо рдХреЗ рдЖрдХрд╛рд░ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, systemLayoutSizeFitting(_:) ред рдЗрд╕ рддрд░рд╣ рдХреА рдЧрдгрдирд╛рдУрдВ рдХреЛ Dictionary , NSCache рдЖрджрд┐ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХреИрд╢реНрдб рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ


рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ, UICollectionView рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рд╕рднреА рд╕реЗрд▓ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рд╕рдВрдЧреНрд░рд╣ рдореЗрдВ рдкреВрд░реНрд╡-рдкрдВрдЬреАрдХреГрдд рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╡рд┐рднрд┐рдиреНрди рд╕реНрдХреНрд░реАрди / рд╕рдВрдЧреНрд░рд╣ рдХреЗ рдмреАрдЪ рд╡рд┐рдЧреЗрдЯреНрд╕ рдХрд╛ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдФрд░ рд╕рднреА рд╕реЗрд▓ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛рдУрдВ / рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рдкрд╣рд▓реЗ рд╕реЗ рдкрдВрдЬреАрдХреГрдд рдирд╣реАрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдПрдХ рддрдВрддреНрд░ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдЬреЛ рдкреНрд░рддреНрдпреЗрдХ рд╕рдВрдЧреНрд░рд╣ рдХреЗ рднреАрддрд░ рдЗрд╕рдХреЗ рдкрд╣рд▓реЗ рдЙрдкрдпреЛрдЧ рд╕реЗ рддреБрд░рдВрдд рдкрд╣рд▓реЗ рдПрдХ рд╕реЗрд▓ рдХреЛ рдкрдВрдЬреАрдХреГрдд рдХрд░реЗрдЧрд╛ред рдкреНрд░рдХрд╛рд╢рди рдореЗрдВ, рдлрд╝рдВрдХреНрд╢рди cellDequeueSafely(indexPath:) рдЙрдкрдпреЛрдЧ рдЗрд╕рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ cellDequeueSafely(indexPath:) ред


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


рдПрдХ рд╣реА рд╕рдВрдЧреНрд░рд╣ рдХреЗ рднреАрддрд░, рдПрдХ рд╣реА рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд╕рд╛рде рд╡рд┐рдЬреЗрдЯ рд╕реНрдерд┐рдд рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╕рдВрдЧреНрд░рд╣ рдХреЗ рдЖрд░рдВрдн рдореЗрдВ рдФрд░ рдЕрдВрдд рдореЗрдВ рд╕рдорд╛рди Spacing ред рдЗрд╕ рддрд░рд╣ рдХреА рдЧреИрд░-рдЕрдиреЛрдЦреА рд╡рд╕реНрддреБрдУрдВ рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ рдЗрд╕ рддрдереНрдп рдХреЛ рдЬрдиреНрдо рджреЗрдЧреА рдХрд┐ рд╕рдВрдЧреНрд░рд╣ рдореЗрдВ рдПрдиреАрдореЗрд╢рди рдЧрд╛рдпрдм рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдРрд╕реА рд╡рд╕реНрддреБрдУрдВ рдХреЛ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк рд╡рд┐рд╢реЗрд╖ AnyHashable рдЯреИрдЧ, #file рдФрд░ #line рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд╣рд╛рдВ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЖрджрд┐ред

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


All Articles