αααααΆααααΈααΆαα
αΌααα½αααααααααα»ααααααααα ααΆααα
WWDC ααααΆα 2019 αααα»αααΆααααααα
α
α·αααα
αΌααααα
αα
αααα»α SwiftUI α αααα»αααΆαα
αααΆααααα
αααΎααααα»αααΆαααααΎααΆαααΆαα½αααΆ α αΎαα₯α‘αΌααααααΆαα
αΆααααααΎααααααΎααααααα·ααΈαα·αααααΆαααααα’αΆα
ααΆααααααααααααα’αααααααΎααααΆααααΆα
αααΎαα
αααα»αααΆαα α
ααΆααΆ MovieSwiftUI - αααααΊααΆαααααα·ααΈαααααΆαααααααααααααααΆαααααααααΈ αα·αα
αΆαα ααααΌα
ααΆααΆααααααΌαααΆαα
αααα»αααααα»ααααααααΎ
ααΎαααααΉαα αααααΆααα’αααα’αΆαααΆααα’αααα "Habr" - ααΆααααα α»αααααα 10 rubles αα αααα α»αααααααααα»ααααααα·ααααΆ Skillbox ααΆαα½ααααααααΎαααααΌαααααααααααΆα "Habr" α
Skillbox ααααΆαα αααααα·ααααΆααΆαα’ααΈαααΊαα·α
"Profession Java Developer" .
ααΌα
ααααααΎ MovieSwiftUI α’αΆα
ααααΎα’αααΈααΆα?
- α’ααααααααααΆαα½α API - ααααΎαααααααααααααα·ααΈααααΎαααααΎααααααα
- αααα»ααα·ααααααα’ααααΆααα
ααΎααααΎ αα·αααα JSON αα
αααα»αααααΌ Swift αααααααΎ
Codable . - αααα αΆαααΌαααΆααααααΆααααα»αααΆαααααΎ αα·ααααααΆαα»ααα½αααΆα
- αααααα·ααΈααααααααΆαα iOS, iPadOS αα·α macOS αααααααΌα UX ααααα’αααα»ααααααΆααα’αααααααΎααααΆααααααααααααααα·ααααα·ααΆαααΆαααααα
- α’αααααααΎααααΆααα’αΆα αααααΎααα·αααααα αα·ααααααΎααααααΈααΆαααααααααΆαααααα½ααααααα½αααα αααααα·ααΈαααααΆαα»α αα·αααααΆααα·ααααααα’αααααααΎααααΆααα
- αα·αααααΆα αααΆαααΆα αα·ααααΌαααααααΌαααΆαααααααααΆαα αααΆαααααααααΎααααΆα Redux α ααα αΌααα·αααααααα ααΈαααααΊααααΆααα·ααα α ααΆα’αΆα ααααΌαααΆαααΆαααααα»αααααΆαααααααΆαααααααα ααααΆα αα·ααααααααΆααααΈααΎα
- αααααα·ααΈααααΎααααΆαααααΆαααΆαα»ααΆααΌαααααΆααα SwiftUI, TabbedView, SegmentedControl, NavigationView, Form, Modal ααΆααΎαα ααΆαααααααααΌααα·αααααΆαααααΆαααααα½α ααΆααα·ααΆα UI/UX αααααα
ααΆαβαα·α α
αααΆβααΊβαααΌα GIF ααΆαβααααβαα
βααΆβαααααααΆααβααααα·α
ααΆαααααΎααΆαααΎαααααα·ααΈααΆααααααα±αααααα»αααΌααααα·αααααααΆα αααΎα α αΎαααΆααΌαα ααΆααΊααΆαααα·ααααααα·αααααΆαα αααα»αβα’αΆα βαααααβαααααα·ααΈβαααβααΆαβαα»αααΆαβαααβαααβ α αΎαβαα βααβαααααΆβαααα»αβααΉαβαααααα’βααΆβα αΎαβαααααααΆαβααΆβαααα»αβ AppStore ααααβααααΆβααΉαβααΆαβα ααβ iOS 13α
Redux, BindableObject αα·α EnvironmentObject
αααα»αααΆαααααΎααΆαααΆαα½α Redux αααα αα XNUMX ααααΆαα αΎα ααΌα
αααααααα»ααααα
αααΆααα’αααΈααΆα ααΆαα·ααααααα»αααααΎααΆαα
αααα»α frontend αααααΆαα
αααα»ααα·αααααααααααΆααααα»αααΆαααααΎαααΎα Redux ααΆααααΆααααααααααα αΌααα·αααααααααααΆαααααααΎααααααα·ααΈ SwiftUI αααααα αααααααααα·ααΆααααα»ααα αααααααΎ Redux αα αααα»ααααααα·ααΈ UIKit αααα»αααααΎααΆαααΆαα½αα αΆα αα·αααα½αααΆα αα·αααΆααααα·αααααα αα·αααΌαααΆααα ααΉααα·αααααΆα/αααΆαααΆαα»ααααα’αααα ααΎααααΈβααααΎβααΌα αααα αααα»αβααααΌαβαααααΎαβαααααΆαααβα§αααααβααααΆααβαα½αβαααααα (αααβααααΎ ReSwift αα·α ReKotlin)α ααααΎαααΆαααΆαααα’ ααα»ααααααΆαααΌαα αααΎαα ααΆα’αα»αα ααΆαα·ααααααΆ (αα·αααΆαα) αααααααΎαα αα ααα
ααααΉαβααα’! ααΏααααα½αααααααααααΌααααα½αααΆααααααΆαα½α SwiftUI - ααααα·αααΎα’αααααΆαααααααααααΎ Redux - ααΊα αΆα αααα αα·αα§αααααααΆαααααααα α’ααααααααααΆαα½αα αΆαααααΌαααΆαααα α·ααααα»αααΆααααΆαααααα»αααα SwiftUI α’ααα»αααα @EnvironmentObject α ααΌα αααα α αΆαα αΆααααααΎαααα BindableObject α
αααα»αααΆααααααΎααααα
αα Swift ααααΆαααααα½α
ααΎααΆααααΎαααΆααααΆαααΌα ααααα ?
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 ααΆααΉαααΌαααααΉαααα SwiftUI αα αααααααααααααααααΆααααΆααααααΌααααααααΎαααααααααααααα· willChange ααααααααααα PassthroughSubject α αααααΊαααααΆααα BindableObject ααααΌαααααααααααααα PublisherType ααα»ααααααΆαα’αα»αααααα·ααΈααΆαααΊααα½ααα»αααααΌααααα»αααΆααααααααααααΆα ααα»ααα αααααΊααΆα§αααααααααΆαα₯αααα·αααααα»αααΈ Apple α ααΌα ααααα αΎα αα αααα»αααααααααΆααααα αΆααααααΆαα 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())
}
}
Store ααααΌαααΆαα αΆαααααα αΌαααΆ EnvironmentObject αα αααααααααααα·ααΈα αΆααααααΎα α αΎααααααΆααααα’αΆα α αΌαααααΎααΆααααα»ααα·αααααΆαααΆαα½ααααααααΎ @EnvironmentObject α αα·αααΆαααΆαααΆααα·αααααΎααΆαα’αα»αααααα ααΈααααααααααααααααααα·αααααα½αααΆαααααΌαααΆαααΆααα α¬ααααΆαααΆααα ααααΈααααΆαααΆααααααα·ααΈα
αααααΌαααΆαααΎααααΆααααααΌαααΌαααΆα ααααα·αααΎααααΆααααΌαααΆαααΆαααααααααΆααααααΌαα
α αΎαααααα·αααΆααααΌαααΆαααααΎαααααααΆαααααα½ααααααΆαα αααααΆααααα½αααααα·αααααΆαααααΌαααΆαααααΆαααα
ααααα ααααα·αααΎα’αααααΆαααααΎααΆαααΆαα½α ReSwift αα
ααΎ iOS α¬ααΌααααΈαα
α₯α‘αΌαβααα α’αααβα’αΆα βααααΆααΆαβααααΎβα±ααβαααααααΆαβααααα αα·αβαααααααΆαβααααβααααΈα αααααΊααΆα§ααΆα ααααααααα»αααααΆαααΆααααα
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!]))
}
}
}
}
αα αααα»αααΌαααΆαααΎ αααα»ααααα»αααααΎαααααααΆα .onDelete ααΈ SwiftUI αααααΆαα IP ααΈαα½ααα ααΆα’αα»ααααΆαα±αααα½αααααααα»ααααααΈαααα αΆαααΆαα’αΌα 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 ααααΆαα
- αααααα·ααααΆααΆααααααα
"α’αααα’αα·ααααααα ααα PRO" .- ααΆαα’αα»αααααααααα·ααααΆααΆαα’ααΈαααΊαα·α
"α’ααααα·ααΆααα·αααααα Python" .- αααααα·ααααΆααΆαααααααααααααααΈαααααΆα
"αααα»αααΆα’ααααααααΎαααα ααααα PRO" .
ααααα: www.habr.com