Leasachadh tagraidh air SwiftUI. Pàirt 1: Dataflow agus Redux

Leasachadh tagraidh air SwiftUI. Pàirt 1: Dataflow agus Redux

Às deidh dhomh a bhith an làthair aig seisean Stàite an Aonaidh aig WWDC 2019, chuir mi romham dàibheadh ​​​​domhainn a-steach do SwiftUI. Tha mi air tòrr ùine a chuir seachad ag obair còmhla ris agus tha mi a-nis air tòiseachadh a’ leasachadh fìor thagradh a dh’ fhaodadh a bhith feumail do raon farsaing de luchd-cleachdaidh.

Thug mi MovieSwiftUI air - is e app a tha seo airson filmichean ùr is sean a lorg, a bharrachd air an cruinneachadh ann an cruinneachadh a’ cleachdadh API TMDB. Bha mi a-riamh dèidheil air filmichean agus eadhon air companaidh a chruthachadh ag obair san raon seo, ged a bha mi o chionn fhada. Cha mhòr gum b’ urrainn don chompanaidh a bhith fionnar, ach bha an tagradh!

Tha sinn a ’cur nar cuimhne: airson a h-uile leughadair de "Habr" - lasachadh de 10 rubles nuair a chlàraicheas tu ann an cùrsa sam bith Skillbox a 'cleachdadh a' chòd adhartachaidh "Habr".

Tha Skillbox a’ moladh: Cùrsa foghlaim air-loidhne "Leasaiche Java Proifeasanta".

Mar sin dè as urrainn dha MovieSwiftUI a dhèanamh?

  • Ag eadar-obrachadh leis an API - bidh cha mhòr tagradh ùr-nodha a’ dèanamh seo.
  • A’ luchdachadh dàta asyncronach air iarrtasan agus a’ parsadh JSON a-steach don mhodal Swift a’ cleachdadh Codail.
  • A’ sealltainn ìomhaighean air an luchdachadh ma thèid an iarraidh agus gan tasgadh.
  • Tha an aplacaid seo airson iOS, iPadOS, agus macOS a’ toirt seachad an UX as fheàrr airson luchd-cleachdaidh nan OSan sin.
  • Faodaidh an neach-cleachdaidh dàta a ghineadh agus na liostaichean film aca fhèin a chruthachadh. Bidh an aplacaid a’ sàbhaladh agus ag ath-nuadhachadh dàta luchd-cleachdaidh.
  • Tha seallaidhean, co-phàirtean agus modailean air an sgaradh gu soilleir a’ cleachdadh pàtran Redux. Tha an sruth dàta an seo aon-stiùiridh. Faodar a làn thasgadh, ath-nuadhachadh agus ath-sgrìobhadh.
  • Bidh an aplacaid a’ cleachdadh na pàirtean bunaiteach de SwiftUI, TabbedView, SegmentedControl, NavigationView, Form, Modal, msaa. Bidh e cuideachd a’ toirt seachad seallaidhean àbhaisteach, gluasadan-bodhaig, UI / UX.

Leasachadh tagraidh air SwiftUI. Pàirt 1: Dataflow agus Redux
Gu dearbh, tha am beòthalachd rèidh, thionndaidh an GIF a-mach beagan borb

Thug a bhith ag obair air an aplacaid tòrr eòlas dhomh agus gu h-iomlan b’ e eòlas math a bh’ ann. Bha e comasach dhomh tagradh làn-ghnìomhach a sgrìobhadh, san t-Sultain leasaichidh mi e agus foillsichidh mi e san AppStore, aig an aon àm ri sgaoileadh iOS 13.

Redux, BindableObject agus EnvironmentObject

Leasachadh tagraidh air SwiftUI. Pàirt 1: Dataflow agus Redux

Tha mi air a bhith ag obair le Redux airson timcheall air dà bhliadhna a-nis, agus mar sin tha mi an ìre mhath eòlach air. Gu sònraichte, bidh mi ga chleachdadh san aghaidh airson React làrach-lìn, a bharrachd air a bhith a’ leasachadh iarrtasan dùthchasach iOS (Swift) agus Android (Kotlin).

Cha robh aithreachas orm a-riamh a bhith a’ taghadh Redux mar an ailtireachd sruthadh dàta airson tagradh SwiftUI a thogail. Is e na pàirtean as dùbhlanaiche nuair a bhios tu a ’cleachdadh Redux ann an app UIKit ag obair leis a’ bhùth agus a ’faighinn agus a’ faighinn dàta air ais agus ga mhapadh a rèir do bheachdan / co-phàirtean. Gus seo a dhèanamh, bha agam ri seòrsa de leabharlann de luchd-ceangail a chruthachadh (a’ cleachdadh ReSwift agus ReKotlin). Ag obair gu math, ach tòrr còd. Gu mì-fhortanach, chan eil e (fhathast) stòr fosgailte.

Deagh naidheachd! Is e na h-aon rudan a tha draghail mu dheidhinn SwiftUI - ma tha thu an dùil Redux a chleachdadh - stòran, stàitean, agus lughdachaidhean. Tha SwiftUI gu tur a’ toirt aire do eadar-obrachadh leis a’ bhùth le taing dha @EnvironmentObject. Mar sin, bidh stòr a’ tòiseachadh le BindableObject.

Chruthaich mi pasgan Swift sìmplidh, SwiftUIFlux, a bheir seachad cleachdadh bunaiteach de Redux. Anns a’ chùis agam tha e na phàirt de MovieSwiftUI. Mise cuideachd sgrìobh oideachadh ceum air cheum, a chuidicheas tu gus am pàirt seo a chleachdadh.

Ciamar a dh'obraicheas e?

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

Gach uair a bhrosnaicheas tu gnìomh, cuiridh tu am bogsa gèar an gnìomh. Nì e measadh air gnìomhan a rèir staid làithreach an tagraidh. Tillidh e an uairsin stàite atharraichte ùr a rèir an seòrsa gnìomh agus an dàta.

Uill, leis gur e BindableObject a th’ ann an stòr, cuiridh e fios gu SwiftUI nuair a dh’ atharraicheas a luach a’ cleachdadh an t-seilbh willChange a thug PassthroughSubject seachad. Tha seo air sgàth gu feum am BindableObject PublisherType a thoirt seachad, ach tha e an urra ri buileachadh a’ phròtacal a riaghladh. Gu h-iomlan, is e inneal fìor chumhachdach a tha seo bho Apple. Mar sin, anns an ath chearcall tairgse, cuidichidh SwiftUI le bhith a’ toirt seachad na beachdan a rèir atharrachadh na stàite.

Gu fìrinneach, is e seo cridhe agus draoidheachd SwiftUI. A-nis, ann an sealladh sam bith a tha fo-sgrìobhadh do stàit, thèid an sealladh a thoirt seachad a rèir dè an dàta a gheibhear bhon stàit agus na tha air atharrachadh.

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

Tha an Stòr air a thoirt a-steach mar EnvironmentObject nuair a thòisicheas an tagradh agus an uairsin gheibhear thuige ann an sealladh sam bith a’ cleachdadh @EnvironmentObject. Chan eil peanas coileanaidh ann leis gu bheil togalaichean a thàinig às a’ faighinn air ais gu sgiobalta no air an tomhas bho staid an tagraidh.

Bidh an còd gu h-àrd ag atharrachadh an ìomhaigh ma dh'atharraicheas am postair film.

Agus tha seo air a dhèanamh le dìreach aon loidhne, le cuideachadh bho na beachdan a tha ceangailte ris an stàit. Ma tha thu air a bhith ag obair le ReSwift air iOS no eadhon ceangal le React, tuigidh tu draoidheachd SwiftUI.

A-nis faodaidh tu feuchainn ris a’ ghnìomh a chuir an gnìomh agus an stàit ùr fhoillseachadh. Seo eisimpleir nas iom-fhillte.

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

Anns a 'chòd gu h-àrd, tha mi a' cleachdadh an gnìomh .onDelete bho SwiftUI airson gach IP. Leigidh seo leis an loidhne san liosta an swipe àbhaisteach iOS a thaisbeanadh airson a sguabadh às. Mar sin nuair a chuireas an neach-cleachdaidh suathadh air a’ phutan cuir às, bidh e a’ piobrachadh a’ ghnìomh fhreagarrach agus a’ toirt air falbh am film bhon liosta.

Uill, leis gu bheil seilbh an liosta a’ tighinn bhon stàit BindableObject agus air a thoirt a-steach mar EnvironmentObject, bidh SwiftUI ag ùrachadh an liosta leis gu bheil ForEach co-cheangailte ri seilbh àireamhaichte nam filmichean.

Seo pàirt den lughdadair MoviesState:

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
}

Thèid an lughdadair a chuir gu bàs nuair a chuireas tu gnìomh air falbh agus nuair a thilleas tu stàite ùr, mar a chaidh a ràdh gu h-àrd.

Cha tèid mi a-steach gu mion-fhiosrachadh fhathast - mar a tha fios aig SwiftUI dha-rìribh dè a thaisbeanadh. Gus seo a thuigsinn nas doimhne, is fhiach e faic seisean WWDC air sruthadh dàta ann an SwiftUI. Tha e cuideachd a’ mìneachadh gu mionaideach carson agus cuin a bu chòir a chleachdadh Stàite, @Binding, ObjectBinding agus EnvironmentObject.

Tha Skillbox a’ moladh:

Source: www.habr.com

Cuir beachd ann