WWDC 2019 рдорд╛ рд╕реНрдЯреЗрдЯ рдЕрдл рдж рдпреБрдирд┐рдпрди рд╕рддреНрд░рдорд╛ рднрд╛рдЧ рд▓рд┐рдПрдкрдЫрд┐, рдореИрд▓реЗ SwiftUI рдорд╛ рдЧрд╣рд┐рд░реЛ рдбреБрдмреНрдиреЗ рдирд┐рд░реНрдгрдп рдЧрд░реЗрдВред рдореИрд▓реЗ рдпрд╕рдХреЛ рд╕рд╛рде рдХрд╛рдо рдЧрд░реНрдиреЗ рдзреЗрд░реИ рд╕рдордп рдмрд┐рддрд╛рдПрдБ рд░ рдЕрдм рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рд╡рд┐рдХрд╛рд╕ рдЧрд░реНрди рдерд╛рд▓реЗрдХреЛ рдЫреБ рдЬреБрди рдкреНрд░рдпреЛрдЧрдХрд░реНрддрд╛рд╣рд░реВрдХреЛ рд╡рд┐рд╕реНрддреГрдд рджрд╛рдпрд░рд╛рдХреЛ рд▓рд╛рдЧрд┐ рдЙрдкрдпреЛрдЧреА рд╣реБрди рд╕рдХреНрдЫред
рдореИрд▓реЗ рдпрд╕рд▓рд╛рдИ MovieSwiftUI рднрдирд┐рдиреНрдЫ - рдпреЛ рдирдпрд╛рдБ рд░ рдкреБрд░рд╛рдирд╛ рдЪрд▓рдЪрд┐рддреНрд░рд╣рд░реВ рдЦреЛрдЬреНрдирдХреЛ рд▓рд╛рдЧрд┐ рдПрдЙрдЯрд╛ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рд╣реЛ, рд╕рд╛рдереИ рддрд┐рдиреАрд╣рд░реВрд▓рд╛рдИ рд╕рдЩреНрдЧреНрд░рд╣рдорд╛ рд╕рдЩреНрдХрд▓рди рдЧрд░реНрдиреЗ
рд╣рд╛рдореА рд╕рдореНрдЭрд╛рдЙрдБрдЫреМрдВ: рд╕рдмреИ Habr рдкрд╛рдардХрд╣рд░реВрдХрд╛ рд▓рд╛рдЧрд┐ - Habr рдкреНрд░реЛрдореЛ рдХреЛрдб рдкреНрд░рдпреЛрдЧ рдЧрд░реА рдХреБрдиреИ рдкрдирд┐ Skillbox рдкрд╛рдареНрдпрдХреНрд░рдордорд╛ рднрд░реНрдирд╛ рдЧрд░реНрджрд╛ резреж,режрежреж рд░реВрдмрд▓ рдЫреБрдЯред
Skillbox рд╕рд┐рдлрд╛рд░рд┐рд╕ рдЧрд░реНрджрдЫ: рд╢реИрдХреНрд╖рд┐рдХ рдЕрдирд▓рд╛рдЗрди рдкрд╛рдареНрдпрдХреНрд░рдо
"рдкреЗрд╢реЗ рдЬрд╛рднрд╛ рд╡рд┐рдХрд╛рд╕рдХрд░реНрддрд╛" .
рддреНрдпрд╕реЛрднрдП MovieSwiftUI рдХреЗ рдЧрд░реНрди рд╕рдХреНрдЫ?
- API рд╕рдБрдЧ рдЕрдиреНрддрд░реНрдХреНрд░рд┐рдпрд╛ рдЧрд░реНрджрдЫ - рд▓рдЧрднрдЧ рдХреБрдиреИ рдкрдирд┐ рдЖрдзреБрдирд┐рдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧрд▓реЗ рдпреЛ рдЧрд░реНрдЫред
- рдЕрдиреБрд░реЛрдзрд╣рд░реВрдорд╛ рдПрд╕рд┐рдиреНрдХреНрд░реЛрдирд╕ рдбреЗрдЯрд╛ рд▓реЛрдб рдЧрд░реНрджрдЫ рд░ JSON рд▓рд╛рдИ рд╕реНрд╡рд┐рдлреНрдЯ рдореЛрдбреЗрд▓ рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ рдкрд╛рд░реНрд╕ рдЧрд░реНрджрдЫ
рдХреЛрдбреЗрдмрд▓ . - рдЕрдиреБрд░реЛрдзрдорд╛ рд▓реЛрдб рдЧрд░рд┐рдПрдХрд╛ рдЫрд╡рд┐рд╣рд░реВ рджреЗрдЦрд╛рдЙрдБрджрдЫ рд░ рддрд┐рдиреАрд╣рд░реВрд▓рд╛рдИ рдХреНрдпрд╛рд╕ рдЧрд░реНрджрдЫред
- iOS, iPadOS, рд░ macOS рдХреЛ рд▓рд╛рдЧрд┐ рдпреЛ рдПрдкрд▓реЗ рдпреА OS рдХрд╛ рдкреНрд░рдпреЛрдЧрдХрд░реНрддрд╛рд╣рд░реВрдХрд╛ рд▓рд╛рдЧрд┐ рдЙрддреНрддрдо UX рдкреНрд░рджрд╛рди рдЧрд░реНрджрдЫред
- рдкреНрд░рдпреЛрдЧрдХрд░реНрддрд╛рд▓реЗ рдбрд╛рдЯрд╛ рдЙрддреНрдкрдиреНрди рдЧрд░реНрди рд░ рдЖрдлреНрдиреИ рдЪрд▓рдЪрд┐рддреНрд░ рд╕реВрдЪреАрд╣рд░реВ рд╕рд┐рд░реНрдЬрдирд╛ рдЧрд░реНрди рд╕рдХреНрдЫред рдЕрдиреБрдкреНрд░рдпреЛрдЧрд▓реЗ рдкреНрд░рдпреЛрдЧрдХрд░реНрддрд╛ рдбреЗрдЯрд╛ рдмрдЪрдд рд░ рдкреБрдирд░реНрд╕реНрдерд╛рдкрдирд╛ рдЧрд░реНрджрдЫред
- рджреГрд╢реНрдп, рдХрдореНрдкреЛрдиреЗрдиреНрдЯ рд░ рдореЛрдбреЗрд▓рд╣рд░реВ Redux рдврд╛рдБрдЪрд╛ рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ рд╕реНрдкрд╖реНрдЯ рд░реВрдкрдорд╛ рдЫреБрдЯреНрдпрд╛рдЗрдПрдХрд╛ рдЫрдиреНред рдпрд╣рд╛рдБ рдбрд╛рдЯрд╛ рдкреНрд░рд╡рд╛рд╣ рджрд┐рд╢рд╛рд╣реАрди рдЫред рдпрд╕рд▓рд╛рдИ рдкреВрд░реНрдг рд░реВрдкрдорд╛ рдХреНрдпрд╛рд╕, рдкреБрдирд░реНрд╕реНрдерд╛рдкрдирд╛ рд░ рдЕрдзрд┐рд▓реЗрдЦрди рдЧрд░реНрди рд╕рдХрд┐рдиреНрдЫред
- рдЕрдиреБрдкреНрд░рдпреЛрдЧрд▓реЗ SwiftUI, TabbedView, SegmentedControl, NavigationView, Form, Modal, рдЖрджрд┐ рдХреЛ рдЖрдзрд╛рд░рднреВрдд рдХрдореНрдкреЛрдиреЗрдиреНрдЯрд╣рд░реВ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрджрдЫред рдпрд╕рд▓реЗ рдЕрдиреБрдХреВрд▓рди рджреГрд╢реНрдпрд╣рд░реВ, рдЗрд╢рд╛рд░рд╛рд╣рд░реВ, UI/UX рдкрдирд┐ рдкреНрд░рджрд╛рди рдЧрд░реНрджрдЫред
рд╡рд╛рд╕реНрддрд╡рдорд╛, рдПрдирд┐рдореЗрд╕рди рдЪрд┐рдХрдиреА рдЫ, GIF рдЕрд▓рд┐рдХрддрд┐ рдЭрдЯрдХрд╛ рднрдпреЛ
рдПрдкрдорд╛ рдХрд╛рдо рдЧрд░реНрджрд╛ рдорд▓рд╛рдИ рдзреЗрд░реИ рдЕрдиреБрднрд╡ рджрд┐рдпреЛ рд░ рд╕рдордЧреНрд░рдорд╛ рдпреЛ рд╕рдХрд╛рд░рд╛рддреНрдордХ рдЕрдиреБрднрд╡ рдерд┐рдпреЛред рдореИрд▓реЗ рдПрдХ рдкреВрд░реНрдг рдХрд╛рд░реНрдпрд╛рддреНрдордХ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рд▓реЗрдЦреНрди рд╕рдХреНрд╖рдо рднрдПрдБ, рд╕реЗрдкреНрдЯреЗрдореНрдмрд░рдорд╛ рдо рдпрд╕рд▓рд╛рдИ рд╕реБрдзрд╛рд░ рдЧрд░реНрдиреЗрдЫреБ рд░ рдпрд╕рд▓рд╛рдИ рдПрдкрд╕реНрдЯреЛрд░рдорд╛ рдкреНрд░рдХрд╛рд╢рд┐рдд рдЧрд░реНрдиреЗрдЫреБ, рдЖрдИрдУрдПрд╕ 13 рдХреЛ рд░рд┐рд▓реАрдЬрдХреЛ рд╕рд╛рдеред
Redux, BindableObject рд░ EnvironmentObject
рдо рд░реЗрдбрдХреНрд╕рд╕рдБрдЧ рд▓рдЧрднрдЧ рджреБрдИ рд╡рд░реНрд╖рджреЗрдЦрд┐ рдХрд╛рдо рдЧрд░рд┐рд░рд╣реЗрдХреЛ рдЫреБ, рддреНрдпрд╕реИрд▓реЗ рдо рдпрд╕рдорд╛ рдЕрдкреЗрдХреНрд╖рд╛рдХреГрдд рд░рд╛рдореНрд░реЛрд╕рдБрдЧ рдирд┐рдкреБрдг рдЫреБред рд╡рд┐рд╢реЗрд╖ рдЧрд░реА, рдо рдпрд╕рд▓рд╛рдИ рдлреНрд░рдиреНрдЯрдПрдиреНрдбрдорд╛ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрджрдЫреБ
рдореИрд▓реЗ рд╕реНрд╡рд┐рдлреНрдЯрдпреВрдЖрдИ рдПрдкреНрд▓рд┐рдХреЗрд╕рди рдирд┐рд░реНрдорд╛рдг рдЧрд░реНрдирдХреЛ рд▓рд╛рдЧрд┐ рдбрд╛рдЯрд╛ рдлреНрд▓реЛ рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░рдХреЛ рд░реВрдкрдорд╛ Redux рдЫрдиреМрдЯ рдЧрд░реЗрдХреЛрдорд╛ рдХрд╣рд┐рд▓реНрдпреИ рдкрдЫреБрддрд╛рдПрдХреЛ рдЫреИрдиред UIKit рдПрдкрдорд╛ Redux рдкреНрд░рдпреЛрдЧ рдЧрд░реНрджрд╛ рд╕рдмреИрднрдиреНрджрд╛ рдЪреБрдиреМрддреАрдкреВрд░реНрдг рднрд╛рдЧрд╣рд░реВ рд╕реНрдЯреЛрд░рд╕рдБрдЧ рдХрд╛рдо рдЧрд░реНрдиреЗ рд░ рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрдиреЗ рд░ рдкреБрди: рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрдиреЗ рд░ рдпрд╕рд▓рд╛рдИ рддрдкрд╛рдИрдВрдХреЛ рджреГрд╢реНрдп/рдХрдореНрдкреЛрдиреЗрдиреНрдЯрд╣рд░реВрдорд╛ рдореНрдпрд╛рдк рдЧрд░реНрдиреЗ рд╣реЛред рдпреЛ рдЧрд░реНрдирдХреЛ рд▓рд╛рдЧрд┐, рдореИрд▓реЗ рдХрдиреЗрдХреНрдЯрд░рд╣рд░реВрдХреЛ рдПрдХ рдкреНрд░рдХрд╛рд░рдХреЛ рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╕рд┐рд░реНрдЬрдирд╛ рдЧрд░реНрдиреБрдкрд░реНтАНрдпреЛ (ReSwift рд░ ReKotlin рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░)ред рд░рд╛рдореНрд░реЛрд╕рдБрдЧ рдХрд╛рдо рдЧрд░реНрджрдЫ, рддрд░ рдзреЗрд░реИ рдХреЛрдбред рджреБрд░реНрднрд╛рдЧреНрдпрд╡рд╢, рдпреЛ (рдЕрдЭреИ) рдЦреБрд▓рд╛ рд╕реНрд░реЛрдд рд╣реЛрдЗрдиред
рдЦреБрд╕реАрдХреЛ рдЦрдмрд░! рд╕реНрд╡рд┐рдлреНрдЯрдпреВрдЖрдИрдХреЛ рд╕рд╛рде рдЪрд┐рдиреНрддрд╛ рдЧрд░реНрдиреЗ рдорд╛рддреНрд░ рдЪреАрдЬрд╣рд░реВ - рдпрджрд┐ рддрдкрд╛рдЗрдБ Redux рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдиреЗ рдпреЛрдЬрдирд╛ рдмрдирд╛рдЙрдиреБрд╣реБрдиреНрдЫ - рд╕реНрдЯреЛрд░рд╣рд░реВ, рд░рд╛рдЬреНрдпрд╣рд░реВ, рд░ рдШрдЯрд╛рдЙрдиреЗрд╣рд░реВ рд╣реБрдиреНред рд╕реНрдЯреЛрд░рд╕рдБрдЧрдХреЛ рдЕрдиреНрддрд░рдХреНрд░рд┐рдпрд╛рд▓рд╛рдИ рд╕реНрд╡рд┐рдлреНрдЯрдпреВрдЖрдИ рджреНрд╡рд╛рд░рд╛ рдкреВрд░реНрдг рд░реВрдкрдорд╛ рд╣реЗрд░рдЪрд╛рд╣ рдЧрд░рд┐рдПрдХреЛ рдЫ @EnvironmentObject рд▓рд╛рдИ рдзрдиреНрдпрд╡рд╛рджред рддреНрдпрд╕реЛрднрдП, рд╕реНрдЯреЛрд░ BindableObject рдмрд╛рдЯ рд╕реБрд░реБ рд╣реБрдиреНрдЫред
рдореИрд▓реЗ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рд╕реНрд╡рд┐рдлреНрдЯ рдкреНрдпрд╛рдХреЗрдЬ рд╕рд┐рд░реНрдЬрдирд╛ рдЧрд░реЗрдВ,
рдпрд╕рд▓реЗ рдХрд╕рд░реА рдХрд╛рдо рдЧрд░реНрдЫ?
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 рд▓реЗ рдПрдХ PublisherType рдкреНрд░рджрд╛рди рдЧрд░реНрдиреБрдкрд░реНрдЫ, рддрд░ рдкреНрд░реЛрдЯреЛрдХрд▓ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдпрд╕рдХреЛ рд╡реНрдпрд╡рд╕реНрдерд╛рдкрдирдХреЛ рд▓рд╛рдЧрд┐ рдЬрд┐рдореНрдореЗрд╡рд╛рд░ рдЫред рд╕рдордЧреНрд░рдорд╛, рдпреЛ рдПрдкреНрдкрд▓рдмрд╛рдЯ рдзреЗрд░реИ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдЙрдкрдХрд░рдг рд╣реЛред рддрджрдиреБрд╕рд╛рд░, рдЕрд░реНрдХреЛ рд░реЗрдиреНрдбрд░рд┐рдЩ рдЪрдХреНрд░рдорд╛, SwiftUI рд▓реЗ рд░рд╛рдЬреНрдп рдкрд░рд┐рд╡рд░реНрддрди рдЕрдиреБрд╕рд╛рд░ рд╡рд┐рдЪрд╛рд░рд╣рд░реВрдХреЛ рдореБрдЦреНрдп рднрд╛рдЧ рдкреНрд░рд╕реНрддреБрдд рдЧрд░реНрди рдорджреНрджрдд рдЧрд░реНрдиреЗрдЫред
рд╡рд╛рд╕реНрддрд╡рдорд╛, рдпреЛ 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())
}
}
рдПрдкреНрд▓рд┐рдХреЗрд╕рди рд╕реБрд░реБ рд╣реБрдБрджрд╛ рд╕реНрдЯреЛрд░рд▓рд╛рдИ EnvironmentObject рдХреЛ рд░реВрдкрдорд╛ рдЗрдиреНрдЬреЗрдХреНрдЯ рдЧрд░рд┐рдиреНрдЫ рд░ рддреНрдпрд╕рдкрдЫрд┐ @EnvironmentObject рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ рдХреБрдиреИ рдкрдирд┐ рджреГрд╢реНрдпрдорд╛ рдкрд╣реБрдБрдЪрдпреЛрдЧреНрдп рд╣реБрдиреНрдЫред рддреНрдпрд╣рд╛рдБ рдХреБрдиреИ рдХрд╛рд░реНрдпрд╕рдореНрдкрд╛рджрди рджрдгреНрдб рдЫреИрди рдХрд┐рдирднрдиреЗ рд╡реНрдпреБрддреНрдкрдиреНрди рдЧреБрдгрд╣рд░реВ рдЫрд┐рдЯреНрдЯреИ рдкреБрди: рдкреНрд░рд╛рдкреНрдд рд╣реБрдиреНрдЫрдиреН рд╡рд╛ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рд╕реНрдерд┐рддрд┐рдмрд╛рдЯ рдЧрдгрдирд╛ рдЧрд░рд┐рдиреНрдЫред
рдорд╛рдерд┐рдХреЛ рдХреЛрдбрд▓реЗ рдЫрд╡рд┐ рдкрд░рд┐рд╡рд░реНрддрди рдЧрд░реНрдЫ рдпрджрд┐ рдЪрд▓рдЪрд┐рддреНрд░ рдкреЛрд╕реНрдЯрд░ рдкрд░рд┐рд╡рд░реНрддрди рд╣реБрдиреНрдЫред
рд░ рдпреЛ рд╡рд╛рд╕реНрддрд╡рдорд╛ рдХреЗрд╡рд▓ рдПрдХ рд▓рд╛рдЗрдирдХреЛ рд╕рд╛рде рдЧрд░рд┐рдиреНрдЫ, рдЬрд╕рдХреЛ рдорджреНрджрддрд▓реЗ рд╡рд┐рдЪрд╛рд░рд╣рд░реВ рд░рд╛рдЬреНрдпрд╕рдБрдЧ рдЬреЛрдбрд┐рдПрдХрд╛ рдЫрдиреНред рдпрджрд┐ рддрдкрд╛рдИрдВрд▓реЗ iOS рдорд╛ ReSwift рд╕рдБрдЧ рдХрд╛рдо рдЧрд░реНрдиреБрднрдПрдХреЛ рдЫ рднрдиреЗ
рдЕрдм рддрдкрд╛рдИрдВ рдХрд╛рд░реНрдп рд╕рдХреНрд░рд┐рдп рдЧрд░реНрди рд░ рдирдпрд╛рдБ рд░рд╛рдЬреНрдп рдкреНрд░рдХрд╛рд╢рд┐рдд рдЧрд░реНрди рдкреНрд░рдпрд╛рд╕ рдЧрд░реНрди рд╕рдХреНрдиреБрд╣реБрдиреНрдЫред рдпрд╣рд╛рдБ рдердк рдЬрдЯрд┐рд▓ рдЙрджрд╛рд╣рд░рдг рд╣реЛред
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 {
// other actions.
case let action as MoviesActions.AddMovieToCustomList:
state.customLists[action.list]?.movies.append(action.movie)
case let action as MoviesActions.RemoveMovieFromCustomList:
state.customLists[action.list]?.movies.removeAll{ $0 == action.movie }
default:
break
}
return state
}
рдорд╛рдерд┐ рдЙрд▓реНрд▓реЗрдЦ рдЧрд░рд┐рдП рдЕрдиреБрд╕рд╛рд░, рддрдкрд╛рдИрдВрд▓реЗ рдХрд╛рд░реНрдп рдкрдард╛рдЙрдБрджрд╛ рд░ рдирдпрд╛рдБ рдЕрд╡рд╕реНрдерд╛ рдлрд░реНрдХрд╛рдЙрдБрджрд╛ рд░рд┐рдбреНрдпреВрд╕рд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реБрдиреНрдЫред
рдо рдЕрдЭреИ рд╡рд┐рд╕реНрддрд╛рд░рдорд╛ рдЬрд╛рдиреЗрдЫреИрди - рдХрд╕рд░реА SwiftUI рд▓рд╛рдИ рд╡рд╛рд╕реНрддрд╡рдорд╛ рдХреЗ рдкреНрд░рджрд░реНрд╢рди рдЧрд░реНрдиреЗ рдерд╛рд╣рд╛ рдЫред рдпрд╕рд▓рд╛рдИ рдЕрдЭ рдЧрд╣рд┐рд░реЛ рд░реВрдкрдорд╛ рдмреБрдЭреНрди, рдпреЛ рд▓рд╛рдпрдХ рдЫ
Skillbox рд╕рд┐рдлрд╛рд░рд┐рд╕ рдЧрд░реНрджрдЫ:
- рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рдкрд╛рдареНрдпрдХреНрд░рдо
"рдореЛрдмрд╛рдЗрд▓ рд╡рд┐рдХрд╛рд╕рдХрд░реНрддрд╛ рдкреНрд░реЛ" .- рдЕрдирд▓рд╛рдЗрди рдкрд╛рдареНрдпрдХреНрд░рдо рд▓рд╛рдЧреВ рдЧрд░рд┐рдпреЛ
"рдкрд╛рдЗрдерди рдбрд╛рдЯрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ" .- рджреБрдИ рд╡рд░реНрд╖реЗ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рдкрд╛рдареНрдпрдХреНрд░рдо
"рдо рдПрдХ рдкреНрд░реЛ рд╡реЗрдм рд╡рд┐рдХрд╛рд╕рдХрд░реНрддрд╛ рд╣реБрдБ" .
рд╕реНрд░реЛрдд: www.habr.com