
WWDC 2019 рдореЗрдВ рдпреВрдирд┐рдпрди рд╕рддреНрд░ рдореЗрдВ рднрд╛рдЧ рд▓реЗрдиреЗ рдХреЗ рдмрд╛рдж, рдореИрдВрдиреЗ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ SwiftUI рдХрд╛ рдЕрдзреНрдпрдпрди рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ред рдореИрдВрдиреЗ рдЙрдирдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдореЗрдВ рдмрд╣реБрдд рд╕рдордп рдмрд┐рддрд╛рдпрд╛ рдФрд░ рдЕрдм рдореИрдВрдиреЗ рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░ рджрд┐рдпрд╛ рд╣реИ рдЬреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреА рдПрдХ рд╡рд┐рд╕реНрддреГрдд рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИред
рдореИрдВрдиреЗ рдЗрд╕реЗ MovieSwiftUI рдХрд╣рд╛ - рдпрд╣ рдирдИ рдФрд░ рдкреБрд░рд╛рдиреА рдлрд┐рд▓реНрдореЛрдВ рдХреЛ рдЦреЛрдЬрдиреЗ рдХреЗ рд╕рд╛рде-рд╕рд╛рде
TMDB API рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЙрдиреНрд╣реЗрдВ рдПрдХ рд╕рдВрдЧреНрд░рд╣ рдореЗрдВ рдПрдХрддреНрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ
рдРрдк рд╣реИ ред рдореИрдВ рд╣рдореЗрд╢рд╛ рдлрд┐рд▓реНрдореЛрдВ рд╕реЗ рдкреНрдпрд╛рд░ рдХрд░рддрд╛ рдерд╛ рдФрд░ рдЗрд╕ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рдХрд╛рдо рдХрд░рдиреЗ рд╡рд╛рд▓реА рдПрдХ рдХрдВрдкрдиреА рднреА рдмрдирд╛рдИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рд▓рдВрдмреЗ рд╕рдордп рддрдХред рдХрдВрдкрдиреА рдХреЛ рд╢рд╛рдВрдд рдХрд╣рдирд╛ рдХрдард┐рди рдерд╛, рд▓реЗрдХрд┐рди рдЖрд╡реЗрджрди - рд╣рд╛рдБ!
рд╣рдо рдЖрдкрдХреЛ рдпрд╛рдж рджрд┐рд▓рд╛рддреЗ рд╣реИрдВ: "рд╣реИрдмрд░" рдХреЗ рд╕рднреА рдкрд╛рдардХреЛрдВ рдХреЗ рд▓рд┐рдП - "рд╣реИрдмрд░" рдкреНрд░реЛрдореЛ рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд┐рд╕реА рднреА рд╕реНрдХрд┐рд▓рдмреЙрдХреНрд╕ рдХреЛрд░реНрд╕ рдХреЗ рд▓рд┐рдП рдкрдВрдЬреАрдХрд░рдг рдХрд░рддреЗ рд╕рдордп 10,000 рд░реВрдмрд▓ рдХреА рдЫреВрдЯред
рд╕реНрдХрд┐рд▓рдмреЙрдХреНрд╕ рдЕрдиреБрд╢рдВрд╕рд╛ рдХрд░рддрд╛ рд╣реИ: рдСрди-рд▓рд╛рдЗрди рд╢реИрдХреНрд╖рд┐рдХ рдкрд╛рдареНрдпрдХреНрд░рдо "рдкреНрд░реЛрдлреЗрд╢рди рдЬрд╛рд╡рд╛-рдбреЗрд╡рд▓рдкрд░" ред
рддреЛ MovieSwiftUI рдХреНрдпрд╛ рдХрд░рддрд╛ рд╣реИ?
- рдПрдкреАрдЖрдИ рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд - рдпрд╣ рд▓рдЧрднрдЧ рдХреЛрдИ рднреА рдЖрдзреБрдирд┐рдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред
- рд▓реЛрдб рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдбреЗрдЯрд╛ рдФрд░ рдкрд╛рд░реНрд╕рд▓ JSON рдХреЛрдбреЗрдмрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕реНрд╡рд┐рдлреНрдЯ рдореЙрдбрд▓ рдореЗрдВред
- рдорд╛рдВрдЧ рдкрд░ рдбрд╛рдЙрдирд▓реЛрдб рдХреА рдЧрдИ рдЫрд╡рд┐рдпреЛрдВ рдХреЛ рджрд┐рдЦрд╛рддрд╛ рд╣реИ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдХреИрд╢ рдХрд░рддрд╛ рд╣реИред
- IOS, iPadOS, рдФрд░ macOS рдХреЗ рд▓рд┐рдП рдпрд╣ рдРрдк рдЗрди OS рдХреЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ UX рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред
- рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдбреЗрдЯрд╛ рдЙрддреНрдкрдиреНрди рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдЕрдкрдиреА рдореВрд╡реА рд╕реВрдЪреА рдмрдирд╛ рд╕рдХрддрд╛ рд╣реИред рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдбреЗрдЯрд╛ рдХреЛ рдмрдЪрд╛рддрд╛ рд╣реИ рдФрд░ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реИред
- Redux рдкреИрдЯрд░реНрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рджреГрд╢реНрдп, рдШрдЯрдХ рдФрд░ рдореЙрдбрд▓ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдЕрд▓рдЧ рдХрд┐рдП рдЧрдП рд╣реИрдВред рдпрд╣рд╛рдВ рдбреЗрдЯрд╛ рд╕реНрдЯреНрд░реАрдо рдпреВрдирд┐рдбрд╛рдпрд░реЗрдХреНрд╢рдирд▓ рд╣реИред рдЗрд╕реЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдХреИрд╢, рд░рд┐рд╕реНрдЯреЛрд░ рдФрд░ рдУрд╡рд░рд░рд╛рдЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
- рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдореВрд▓ рдШрдЯрдХреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ SwiftUI, TabbedView, SegmentedControl, NavigationView, рдкреНрд░рдкрддреНрд░, рдореЛрдбрд▓, рдЖрджрд┐ред рдпрд╣ рдХрд╕реНрдЯрдо рд╡реНрдпреВ, рдЬреЗрд╕реНрдЪрд░, UI / UX рднреА рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред
рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдПрдиреАрдореЗрд╢рди рдЪрд┐рдХрдиреА рд╣реИ, GIF рдереЛрдбрд╝рд╛ рдЪрд┐рдХреЛрдЯреА рдирд┐рдХрд▓рд╛рдЖрд╡реЗрджрди рдкрд░ рдХрд╛рдо рдХрд░рдиреЗ рд╕реЗ рдореБрдЭреЗ рдмрд╣реБрдд рдЕрдиреБрднрд╡ рдорд┐рд▓рд╛, рдФрд░ рдХреБрд▓ рдорд┐рд▓рд╛рдХрд░ рдпрд╣ рдПрдХ рд╕рдХрд╛рд░рд╛рддреНрдордХ рдЕрдиреБрднрд╡ рд╣реИред рдореИрдВ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд▓рд┐рдЦрдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдерд╛, рд╕рд┐рддрдВрдмрд░ рдореЗрдВ рдореИрдВ рдЗрд╕реЗ рд╕реБрдзрд╛рд░реВрдВрдЧрд╛ рдФрд░ рдЗрд╕реЗ iOS 13 рдХреА рд░рд┐рд▓реАрдЬ рдХреЗ рд╕рд╛рде, AppStore рдореЗрдВ рдбрд╛рд▓реВрдВрдЧрд╛ред
Redux, BindableObject, рдФрд░ EnvironmentObject

рдореИрдВ рдЕрдм Redux рдХреЗ рд╕рд╛рде рд▓рдЧрднрдЧ рджреЛ рд╕рд╛рд▓ рд╕реЗ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рдЗрд╕рд▓рд┐рдП рдореБрдЭреЗ рдпрд╣ рдЕрдкреЗрдХреНрд╖рд╛рдХреГрдд рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдкрддрд╛ рд╣реИред рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ, рдореИрдВ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ
рд░рд┐рдПрдХреНрдЯ рд╡реЗрдмрд╕рд╛рдЗрдЯ рдХреЗ рдлреНрд░рдВрдЯрдПрдВрдб рдореЗрдВ, рд╕рд╛рде рд╣реА рд╕рд╛рде рджреЗрд╢реА рдЖрдИрдУрдПрд╕ (рд╕реНрд╡рд┐рдлреНрдЯ) рдФрд░ рдПрдВрдбреНрд░реЙрдЗрдб (рдХреЛрдЯрд▓рд┐рди) рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЛ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд░рддрд╛ рд╣реВрдВред
рдореИрдВрдиреЗ SwiftUI рдкрд░ рдПрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛ рдкреНрд░рд╡рд╛рд╣ рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдХреЗ рд░реВрдк рдореЗрдВ Redux рдХреЛ рдЪреБрдирдиреЗ рдХрд╛ рдХрднреА рдЕрдлрд╕реЛрд╕ рдирд╣реАрдВ рдХрд┐рдпрд╛ред UIKit рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ Redux рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп рд╕рдмрд╕реЗ рдХрдард┐рди рдХреНрд╖рдгреЛрдВ рдореЗрдВ рд╕реНрдЯреЛрд░ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рд╕рд╛рде рд╣реА рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдФрд░ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдФрд░ рдЕрдкрдиреЗ рд╡рд┐рдЪрд╛рд░реЛрдВ / рдШрдЯрдХреЛрдВ рдХреЗ рд╕рд╛рде рддреБрд▓рдирд╛ рдХрд░рдирд╛ред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореБрдЭреЗ рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреА рдХрдиреЗрдХреНрдЯрд░ рд▓рд╛рдЗрдмреНрд░реЗрд░реА (рд░реАрд╕реНрд╡рд┐рдлрд╝реНрдЯ рдФрд░ рд░реЗрдХреЛрдЯрд▓рд┐рди рдкрд░) рдмрдирд╛рдиреА рдкрдбрд╝реАред рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХрд╛рдлреА рдХреЛрдбред рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рдпрд╣ рдЦреБрд▓рд╛ рд╕реНрд░реЛрдд рдирд╣реАрдВ рд╣реИред
рдЕрдЪреНрдЫреА рдЦрдмрд░ рд╣реИ! SwiftUI рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЪрд┐рдВрддрд╛ рдХрд░рдиреЗ рд╡рд╛рд▓реА рдПрдХрдорд╛рддреНрд░ рдЪреАрдЬрд╝ - рдпрджрд┐ рдЖрдк Redux рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдпреЛрдЬрдирд╛ рдмрдирд╛рддреЗ рд╣реИрдВ - рд╕реНрдЯреЛрд░, рд╕реНрдЯреЗрдЯреНрд╕ рдФрд░ рд░рд┐рдбреНрдпреВрд╕рд░ рд╣реИрдВред рд╕реНрд╡рд┐рдлреНрдЯрдпреВрдЖрдИ рдиреЗ @EnvironmentObject рдХреЗ рд▓рд┐рдП рд╕реНрдЯреЛрд░ рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рдХреАред рддреЛ, рд╕реНрдЯреЛрд░ BindableObject рд╕реЗ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИред
рдореИрдВрдиреЗ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рд╕реНрд╡рд┐рдлреНрдЯ рдкреИрдХреЗрдЬ рдмрдирд╛рдпрд╛, рд╕реНрд╡рд┐рдлреНрдЯ
рдпреВрдлреНрд▓рдХреНрд╕ , рдЬреЛ
рд░реЗрдбрдХреНрд╕ рдХрд╛ рдореВрд▓ рдЙрдкрдпреЛрдЧ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рдореЗрд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ MovieSwiftUI рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИред рдореИрдВрдиреЗ рдЗрд╕ рдШрдЯрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдореЗрдВ рдЖрдкрдХреА рдорджрдж рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП
рдПрдХ рдЪрд░рдг-рджрд░-рдЪрд░рдг рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рднреА
рд▓рд┐рдЦрд╛ рд╣реИ ред
рдпрд╣ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ?final public class Store<State: FluxState>: BindableObject { public let willChange = PassthroughSubject<Void, Never>() private(set) public var state: State private func _dispatch(action: Action) { willChange.send() state = reducer(state, action) } }
рд╣рд░ рдмрд╛рд░ рдЬрдм рдЖрдк рдХрд╛рд░реНрд░рд╡рд╛рдИ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдЧрд┐рдпрд░рдмреЙрдХреНрд╕ рдХреЛ рд╕рдХреНрд░рд┐рдп рдХрд░рддреЗ рд╣реИрдВред рд╡рд╣ рдЖрд╡реЗрджрди рдХреА рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдореВрд▓реНрдпрд╛рдВрдХрди рдХрд░реЗрдЧрд╛ред рдлрд┐рд░ рдпрд╣ рдХреНрд░рд┐рдпрд╛ рдФрд░ рдбреЗрдЯрд╛ рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдПрдХ рдирдпрд╛ рд╕рдВрд╢реЛрдзрд┐рдд рд░рд╛рдЬреНрдп рд▓реМрдЯрд╛рдПрдЧрд╛ред
рдЦреИрд░, рдЪреВрдБрдХрд┐ рд╕реНрдЯреЛрд░ рдПрдХ BindableObject рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ PassthroughSubject рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдХреА рдЬрд╛рдиреЗ рд╡рд╛рд▓реА WillChange рд╕рдВрдкрддреНрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЕрдкрдиреЗ рдореВрд▓реНрдп рдореЗрдВ рдмрджрд▓рд╛рд╡ рдХреЗ SwiftUI рдХреЛ рд╕реВрдЪрд┐рдд рдХрд░реЗрдЧрд╛ред рдРрд╕рд╛ рдЗрд╕рд▓рд┐рдП рд╣реИ рдХреНрдпреЛрдВрдХрд┐ BindableObject рдХреЛ Publisher рдЯрд╛рдЗрдк рдкреНрд░рджрд╛рди рдХрд░рдирд╛ рд╣реЛрдЧрд╛, рд▓реЗрдХрд┐рди рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЗрд╕рдХреЗ рдкреНрд░рдмрдВрдзрди рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИред рд╕рдм рдХреЗ рд╕рдм, рдпрд╣ Apple рдХрд╛ рдПрдХ рдмрд╣реБрдд рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдЙрдкрдХрд░рдг рд╣реИред рддрджрдиреБрд╕рд╛рд░, рдЕрдЧрд▓реЗ рд░реЗрдВрдбрд░рд┐рдВрдЧ рдЪрдХреНрд░ рдореЗрдВ, SwiftUI рд░рд╛рдЬреНрдп рдкрд░рд┐рд╡рд░реНрддрди рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХреЗ рд╢рд░реАрд░ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдЧрд╛ред
рджрд░рдЕрд╕рд▓, рдпрд╣ рд╕рдм рд╣реИ - рд╕реНрд╡рд┐рдлреНрдЯрдпреВрдЖрдИ рдХрд╛ рджрд┐рд▓ рдФрд░ рдЬрд╛рджреВред рдЕрдм, рдХрд┐рд╕реА рднреА рджреГрд╢реНрдп рдореЗрдВ, рдЬрд┐рд╕реЗ рдХрд┐рд╕реА рд░рд╛рдЬреНрдп рдХреА рд╕рджрд╕реНрдпрддрд╛ рджреА рдЬрд╛рддреА рд╣реИ, рдпрд╣ рджреГрд╢реНрдп рдЙрд╕ рд╕реНрдерд┐рддрд┐ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдЬреЛ рд░рд╛рдЬреНрдп рд╕реЗ рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ рдФрд░ рдЬреЛ рдмрджрд▓ рдЧрдпрд╛ рд╣реИред
class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { if let windowScene = scene as? UIWindowScene { let window = UIWindow(windowScene: windowScene) let controller = UIHostingController(rootView: HomeView().environmentObject(store)) window.rootViewController = controller self.window = window window.makeKeyAndVisible() } } } struct CustomListCoverRow : View { @EnvironmentObject var store: Store<AppState> let movieId: Int var movie: Movie! { return store.state.moviesState.movies[movieId] } var body: some View { HStack(alignment: .center, spacing: 0) { Image(movie.poster) }.listRowInsets(EdgeInsets()) } }
рдЬрдм рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдкреНрд░рд╛рд░рдВрдн рд╣реЛрддрд╛ рд╣реИ, рддрдм Store рдПрдХ EnvironmentObject рдХреЗ рд░реВрдк рдореЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдлрд┐рд░ @EnvironmentObject рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд┐рд╕реА рднреА рджреГрд╢реНрдп рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╣реЛрддрд╛ рд╣реИред рдкреНрд░рджрд░реНрд╢рди рдХреЛ рдХрдо рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рд╡реНрдпреБрддреНрдкрдиреНрди рдЧреБрдгреЛрдВ рдХреЛ рдЬрд▓реНрджреА рд╕реЗ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдпрд╛ рдЖрд╡реЗрджрди рд╕реНрдерд┐рддрд┐ рд╕реЗ рдЧрдгрдирд╛ рдХреА рдЬрд╛рддреА рд╣реИред
рдпрджрд┐ рдлрд┐рд▓реНрдо рдХреЗ рд▓рд┐рдП рдкреЛрд╕реНрдЯрд░ рдореЗрдВ рдмрджрд▓рд╛рд╡ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдКрдкрд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рдХреЛрдб рдЫрд╡рд┐ рдмрджрд▓рддрд╛ рд╣реИред
рдФрд░ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╕рд┐рд░реНрдл рдПрдХ рдкрдВрдХреНрддрд┐ рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреА рдорджрдж рд╕реЗ рд░рд╛рдЬреНрдп рд╕реЗ рд╡рд┐рдЪрд╛рд░ рдЬреБрдбрд╝реЗ рд╣реБрдП рд╣реИрдВред рдпрджрд┐ рдЖрдкрдиреЗ iOS рдкрд░ ReSwift рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд┐рдпрд╛ рд╣реИ рдпрд╛ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ React рд╕реЗ
рдЬреБрдбрд╝рддреЗ рд╣реИрдВ , рддреЛ рдЖрдк рд╕рдордЭреЗрдВрдЧреЗ рдХрд┐ SwiftUI рдЬрд╛рджреВ рдХреНрдпрд╛ рд╣реИред
рдФрд░ рдЕрдм рдЖрдк рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЛ рд╕рдХреНрд░рд┐рдп рдХрд░рдиреЗ рдФрд░ рдПрдХ рдирдпрд╛ рд░рд╛рдЬреНрдп рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣рд╛рдБ рдПрдХ рдФрд░ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рдЙрджрд╛рд╣рд░рдг рд╣реИред
struct CustomListDetail : View { @EnvironmentObject var store: Store<AppState> let listId: Int var list: CustomList { store.state.moviesState.customLists[listId]! } var movies: [Int] { list.movies.sortedMoviesIds(by: .byReleaseDate, state: store.state) } var body: some View { List { ForEach(movies) { movie in NavigationLink(destination: MovieDetail(movieId: movie).environmentObject(self.store)) { MovieRow(movieId: movie, displayListImage: false) } }.onDelete { (index) in self.store.dispatch(action: MoviesActions.RemoveMovieFromCustomList(list: self.listId, movie: self.movies[index.first!])) } } } }
рдКрдкрд░ рджрд┐рдП рдЧрдП рдХреЛрдб рдореЗрдВ, рдореИрдВ рдкреНрд░рддреНрдпреЗрдХ IP рдХреЗ рд▓рд┐рдП SwiftUI рд╕реЗ .onDelete рдХреНрд░рд┐рдпрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВред рдпрд╣ рд╕реВрдЪреА рдореЗрдВ рд▓рд╛рдЗрди рдХреЛ рд╣рдЯрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд╛рдорд╛рдиреНрдп iOS рд╕реНрд╡рд╛рдЗрдк рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдЬрдм рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдбрд┐рд▓реАрдЯ рдмрдЯрди рдХреЛ рдЫреВрддрд╛ рд╣реИ, рддреЛ рд╡рд╣ рд╕рдВрдмрдВрдзрд┐рдд рдХрд╛рд░реНрд░рд╡рд╛рдИ рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдлрд┐рд▓реНрдо рдХреЛ рд╕реВрдЪреА рд╕реЗ рд╣рдЯрд╛ рджреЗрддрд╛ рд╣реИред
рдЦреИрд░, рдЪреВрдВрдХрд┐ рд╕реВрдЪреА рд╕рдВрдкрддреНрддрд┐ рдХреЛ BindableObject рдХреА рд╕реНрдерд┐рддрд┐ рд╕реЗ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рдПрдХ EnvironmentObject рдХреЗ рд░реВрдк рдореЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП SwiftUI рд╕реВрдЪреА рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ ForEach рдЧрдгрдирд╛ рдХреА рдЧрдИ рдлрд┐рд▓реНрдо рд╕рдВрдкрддреНрддрд┐ рдХреЗ рд╕рд╛рде рдЬреБрдбрд╝рд╛ рд╣реБрдЖ рд╣реИред
рдпрд╣рд╛рдБ MoviesState reducer рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИ:
func moviesStateReducer(state: MoviesState, action: Action) -> MoviesState { var state = state switch action {
Reducer рдХреЛ рддрдм рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрдм рдЖрдк рдХрд╛рд░реНрд░рд╡рд╛рдИ рд╕рдмрдорд┐рдЯ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рдирдпрд╛ рд░рд╛рдЬреНрдп рд╡рд╛рдкрд╕ рдХрд░рддреЗ рд╣реИрдВ, рдЬреИрд╕рд╛ рдХрд┐ рдКрдкрд░ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред
рдореИрдВ рдЕрднреА рдХреЗ рд▓рд┐рдП рд╡рд┐рд╡рд░рдг рдореЗрдВ рдирд╣реАрдВ рдЬрд╛рдКрдВрдЧрд╛ - рд╕реНрд╡рд┐рдлреНрдЯрдпреВрдЖрдИ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреИрд╕реЗ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИред рдЗрд╕реЗ рдФрд░ рдЧрд╣рд░рд╛рдИ рд╕реЗ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ SwiftUI рдореЗрдВ
рдбреЗрдЯрд╛ рдкреНрд░рд╡рд╛рд╣ рдкрд░ WWDC рд╕рддреНрд░ рдХреЛ
рджреЗрдЦрдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрд╣ рднреА рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рдмрддрд╛рддрд╛ рд╣реИ рдХрд┐ рдХреНрдпреЛрдВ, рдХрдм рдФрд░ рдХреИрд╕реЗ
рд░рд╛рдЬреНрдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ, @Binding, ObjectBinding, рдФрд░ EnvironmentObjectред
рд╕реНрдХрд┐рд▓рдмреЙрдХреНрд╕ рдЕрдиреБрд╢рдВрд╕рд╛ рдХрд░рддрд╛ рд╣реИ: