Pag-uswag sa aplikasyon sa SwiftUI. Bahin 1: Dataflow ug Redux

Pag-uswag sa aplikasyon sa SwiftUI. Bahin 1: Dataflow ug Redux

Pagkahuman sa pagtambong sa sesyon sa State of the Union sa WWDC 2019, nakahukom ko nga mag-dive sa SwiftUI. Naggugol ako og daghang oras sa pagtrabaho niini ug karon nagsugod na sa paghimo og usa ka tinuod nga aplikasyon nga mahimong mapuslanon sa daghang mga tiggamit.

Gitawag ko kini nga MovieSwiftUI - kini usa ka app alang sa pagpangita sa bag-o ug daan nga mga pelikula, ingon man pagkolekta niini sa usa ka koleksyon gamit ang TMDB API. Kanunay kong ganahan og mga pelikula ug nagmugna pa gani og kompanya nga nagtrabaho niini nga natad, bisan tuod dugay na ang milabay. Ang kompanya halos dili matawag nga cool, apan ang aplikasyon mao!

Gipahinumduman namon ikaw: alang sa tanan nga mga magbabasa sa "Habr" - usa ka diskwento sa 10 nga mga rubles kung nagpalista sa bisan unsang kurso sa Skillbox gamit ang code sa promosyon nga "Habr".

Girekomenda sa Skillbox: Online nga kurso sa edukasyon "Propesyon nga Java Developer".

Busa unsa ang mahimo sa MovieSwiftUI?

  • Nakig-interact sa API - halos bisan unsang modernong aplikasyon naghimo niini.
  • Nag-load sa asynchronous nga datos sa mga hangyo ug nag-parse sa JSON ngadto sa Swift nga modelo gamit Codable.
  • Nagpakita sa mga hulagway nga gikarga sa hangyo ug gi-cache kini.
  • Kini nga app alang sa iOS, iPadOS, ug macOS naghatag sa labing kaayo nga UX alang sa mga tiggamit niini nga mga OS.
  • Ang tiggamit makahimo og data ug makahimo sa ilang kaugalingong mga listahan sa salida. Ang aplikasyon nagtipig ug nagpahiuli sa datos sa tiggamit.
  • Ang mga pagtan-aw, mga sangkap ug mga modelo klaro nga gibulag gamit ang pattern sa Redux. Ang dagan sa datos dinhi kay unidirectional. Mahimo kini nga hingpit nga ma-cache, ibalik ug ma-overwrite.
  • Gigamit sa aplikasyon ang mga batakang sangkap sa SwiftUI, TabbedView, SegmentedControl, NavigationView, Form, Modal, ug uban pa. Naghatag usab kini og mga kostumbre nga pagtan-aw, mga lihok, UI / UX.

Pag-uswag sa aplikasyon sa SwiftUI. Bahin 1: Dataflow ug Redux
Sa tinuud, hapsay ang animation, ang GIF nahimo’g gamay nga jerky

Ang pagtrabaho sa app naghatag kanako og daghang kasinatian ug sa kinatibuk-an kini usa ka positibo nga kasinatian. Nakasulat ako usa ka hingpit nga magamit nga aplikasyon, sa Septyembre pauswagon ko kini ug imantala kini sa AppStore, dungan sa pagpagawas sa iOS 13.

Redux, BindableObject ug EnvironmentObject

Pag-uswag sa aplikasyon sa SwiftUI. Bahin 1: Dataflow ug Redux

Nagtrabaho ko sa Redux mga duha ka tuig na karon, mao nga medyo batid na ako niini. Sa partikular, gigamit nako kini sa frontend alang sa React website, ingon man alang sa pagpalambo sa lumad nga iOS (Swift) ug Android (Kotlin) nga mga aplikasyon.

Wala gyud ko nagbasol sa pagpili sa Redux isip arkitektura sa daloy sa datos alang sa pagtukod sa usa ka aplikasyon sa SwiftUI. Ang labing hagit nga mga bahin kung gigamit ang Redux sa usa ka UIKit app nagtrabaho kauban ang tindahan ug pagkuha ug pagkuha sa datos ug pagmapa niini sa imong mga panan-aw / sangkap. Aron mahimo kini, kinahanglan kong maghimo usa ka klase nga librarya sa mga konektor (gamit ang ReSwift ug ReKotlin). Maayo ang pagtrabaho, apan daghang code. Ikasubo, kini dili (pa) bukas nga tinubdan.

Maayong Balita! Ang mga butang ra nga mabalaka bahin sa SwiftUI - kung nagplano ka nga mogamit sa Redux - mao ang mga tindahan, estado, ug mga reducer. Ang pakigsulti sa tindahan hingpit nga giatiman sa SwiftUI salamat sa @EnvironmentObject. Busa, ang tindahan nagsugod sa usa ka BindableObject.

Naghimo ako usa ka yano nga pakete sa Swift, SwiftUIFlux, nga naghatag ug batakang paggamit sa Redux. Sa akong kaso kini bahin sa MovieSwiftUI. Ako usab misulat sa usa ka lakang-sa-lakang nga panudlo, nga makatabang kanimo sa paggamit niini nga sangkap.

Unsang paagi kini sa trabaho?

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)
    }
}

Matag higayon nga mag-trigger ka og aksyon, imong gi-activate ang gearbox. Susihon niini ang mga aksyon sumala sa karon nga kahimtang sa aplikasyon. Kini unya mobalik sa usa ka bag-o nga giusab nga estado sumala sa aksyon nga matang ug data.

Aw, tungod kay ang tindahan usa ka BindableObject, kini magpahibalo sa SwiftUI kung ang kantidad niini mausab gamit ang willChange property nga gihatag sa PassthroughSubject. Kini tungod kay ang BindableObject kinahanglang maghatag ug PublisherType, apan ang pagpatuman sa protocol maoy responsable sa pagdumala niini. Sa kinatibuk-an, kini usa ka gamhanan kaayo nga himan gikan sa Apple. Tungod niini, sa sunod nga siklo sa paghubad, ang SwiftUI makatabang sa paghubad sa lawas sa mga panan-aw sumala sa pagbag-o sa estado.

Sa tinuud, kini ang tanan nga kasingkasing ug salamangka sa SwiftUI. Karon, sa bisan unsang pagtan-aw nga nag-subscribe sa usa ka estado, ang pagtan-aw igahatag sumala sa kung unsang datos ang nadawat gikan sa estado ug kung unsa ang nabag-o.

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())
    }
}

Ang Tindahan gi-injected isip usa ka EnvironmentObject kung magsugod ang aplikasyon ug dayon ma-access sa bisan unsang pagtan-aw gamit ang @EnvironmentObject. Wala’y silot sa pasundayag tungod kay ang nakuha nga mga kabtangan dali nga makuha o kalkulado gikan sa kahimtang sa aplikasyon.

Ang code sa ibabaw nagbag-o sa imahe kung ang poster sa salida mausab.

Ug kini sa tinuud gihimo sa usa lang ka linya, sa tabang kung unsang mga panan-aw ang konektado sa estado. Kung nagtrabaho ka sa ReSwift sa iOS o bisan Sumpaysumpaya uban sa React, masabtan nimo ang salamangka sa SwiftUI.

Karon mahimo nimong sulayan nga ma-aktibo ang aksyon ug imantala ang bag-ong estado. Ania ang usa ka mas komplikado nga pananglitan.

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!]))
            }
        }
    }
}

Sa code sa ibabaw, akong gigamit ang .onDelete nga aksyon gikan sa SwiftUI alang sa matag IP. Gitugotan niini ang laray sa lista nga ipakita ang normal nga pag-swipe sa iOS aron mapapas. Mao nga kung gihikap sa tiggamit ang buton sa pagtangtang, kini nagpalihok sa katugbang nga aksyon ug gitangtang ang salida gikan sa lista.

Aw, tungod kay ang listahan nga kabtangan nakuha gikan sa BindableObject nga estado ug gi-injected isip EnvironmentObject, gi-update sa SwiftUI ang listahan tungod kay ang ForEach nalangkit sa mga salida nga kalkulado nga kabtangan.

Ania ang bahin sa 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
}

Ang reducer gipatuman kung nagpadala ka usa ka aksyon ug ibalik ang usa ka bag-ong estado, ingon sa giingon sa ibabaw.

Dili pa nako hisgotan ang detalye - kung giunsa nahibal-an sa SwiftUI kung unsa ang ipakita. Aron masabtan kini nga mas lawom, takus kini tan-awa ang sesyon sa WWDC sa dagan sa datos sa SwiftUI. Gipatin-aw usab niini sa detalye kung ngano ug kanus-a gamiton State, @Binding, ObjectBinding ug EnvironmentObject.

Girekomenda sa Skillbox:

Source: www.habr.com

Idugang sa usa ka comment