Datblygu cymwysiadau ar SwiftUI. Rhan 1: Dataflow a Redux

Datblygu cymwysiadau ar SwiftUI. Rhan 1: Dataflow a Redux

Ar ôl mynychu sesiwn Cyflwr yr Undeb yn WWDC 2019, penderfynais blymio'n ddwfn i SwiftUI. Rwyf wedi treulio llawer o amser yn gweithio gydag ef ac rwyf bellach wedi dechrau datblygu cymhwysiad go iawn a all fod yn ddefnyddiol i ystod eang o ddefnyddwyr.

Gelwais ef yn MovieSwiftUI - mae hwn yn ap ar gyfer chwilio am ffilmiau hen a newydd, yn ogystal â'u casglu mewn casgliad gan ddefnyddio API TMDB. Rwyf bob amser wedi caru ffilmiau a hyd yn oed wedi creu cwmni yn gweithio yn y maes hwn, er amser maith yn ôl. Prin y gellid galw y cwmni yn cŵl, ond roedd y cais!

Rydym yn atgoffa: i holl ddarllenwyr "Habr" - gostyngiad o 10 rubles wrth gofrestru ar unrhyw gwrs Skillbox gan ddefnyddio'r cod hyrwyddo "Habr".

Mae Skillsbox yn argymell: Cwrs addysgol ar-lein "Datblygwr Java Proffesiynol".

Felly beth all MovieSwiftUI ei wneud?

  • Yn rhyngweithio â'r API - mae bron unrhyw raglen fodern yn gwneud hyn.
  • Yn llwytho data anghydamserol ar geisiadau ac yn dosrannu JSON i'r model Swift gan ddefnyddio Codadwy.
  • Yn dangos delweddau wedi'u llwytho ar gais ac yn eu storio.
  • Mae'r ap hwn ar gyfer iOS, iPadOS, a macOS yn darparu'r UX gorau i ddefnyddwyr yr OSau hyn.
  • Gall y defnyddiwr gynhyrchu data a chreu eu rhestrau ffilm eu hunain. Mae'r rhaglen yn arbed ac yn adfer data defnyddwyr.
  • Mae golygfeydd, cydrannau a modelau wedi'u gwahanu'n glir gan ddefnyddio patrwm Redux. Mae'r llif data yma yn un cyfeiriad. Gellir ei storio'n llawn, ei adfer a'i drosysgrifo.
  • Mae'r rhaglen yn defnyddio cydrannau sylfaenol SwiftUI, TabbedView, SegmentedControl, NavigationView, Form, Modal, ac ati. Mae hefyd yn darparu golygfeydd personol, ystumiau, UI / UX.

Datblygu cymwysiadau ar SwiftUI. Rhan 1: Dataflow a Redux
Mewn gwirionedd, mae'r animeiddiad yn llyfn, trodd y GIF allan ychydig yn herciog

Rhoddodd gweithio ar yr ap lawer o brofiad i mi ac yn gyffredinol roedd yn brofiad cadarnhaol. Llwyddais i ysgrifennu cymhwysiad cwbl weithredol, ym mis Medi byddaf yn ei wella ac yn ei gyhoeddi yn yr AppStore, ar yr un pryd â rhyddhau iOS 13.

Redux, BindableObject ac EnvironmentObject

Datblygu cymwysiadau ar SwiftUI. Rhan 1: Dataflow a Redux

Rwyf wedi bod yn gweithio gyda Redux ers tua dwy flynedd bellach, felly rwy'n gymharol hyddysg ynddo. Yn benodol, rwy'n ei ddefnyddio yn y blaen ar gyfer Ymateb gwefan, yn ogystal ag ar gyfer datblygu cymwysiadau iOS (Swift) ac Android (Kotlin) brodorol.

Nid wyf erioed wedi difaru dewis Redux fel y bensaernïaeth llif data ar gyfer adeiladu cymhwysiad SwiftUI. Y rhannau mwyaf heriol wrth ddefnyddio Redux mewn ap UIKit yw gweithio gyda'r siop a chael ac adfer data a'i fapio i'ch barn / cydrannau. I wneud hyn, roedd yn rhaid i mi greu math o lyfrgell o gysylltwyr (gan ddefnyddio ReSwift a ReKotlin). Yn gweithio'n dda, ond cryn dipyn o god. Yn anffodus, nid yw (eto) yn ffynhonnell agored.

Newyddion da! Yr unig bethau i boeni amdanynt gyda SwiftUI - os ydych chi'n bwriadu defnyddio Redux - yw siopau, taleithiau a gostyngwyr. Mae SwiftUI yn cymryd gofal llwyr o ryngweithio â'r siop diolch i @EnvironmentObject. Felly, mae storfa'n dechrau gyda BindableObject.

Creais becyn Swift syml, SwiftUIFlux, sy'n darparu defnydd sylfaenol o Redux. Yn fy achos i mae'n rhan o MovieSwiftUI. Rydw i hefyd ysgrifennu tiwtorial cam wrth gam, a fydd yn eich helpu i ddefnyddio'r gydran hon.

Sut mae'n gweithio?

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

Bob tro y byddwch chi'n sbarduno gweithred, rydych chi'n actifadu'r blwch gêr. Bydd yn gwerthuso camau gweithredu yn ôl cyflwr presennol y cais. Yna bydd yn dychwelyd cyflwr addasedig newydd yn unol â'r math o weithred a'r data.

Wel, gan fod storfa yn BindableObject, bydd yn hysbysu SwiftUI pan fydd ei werth yn newid gan ddefnyddio'r eiddo willChange a ddarperir gan PassthroughSubject. Mae hyn oherwydd bod yn rhaid i'r BindableObject ddarparu PublisherType, ond gweithredu'r protocol sy'n gyfrifol am ei reoli. Ar y cyfan, mae hwn yn offeryn pwerus iawn gan Apple. Yn unol â hynny, yn y cylch rendro nesaf, bydd SwiftUI yn helpu i roi corff y safbwyntiau yn ôl y newid cyflwr.

A dweud y gwir, dyma holl galon a hud SwiftUI. Nawr, mewn unrhyw farn sy'n tanysgrifio i gyflwr, bydd y farn yn cael ei rhoi yn ôl pa ddata a dderbynnir gan y wladwriaeth a'r hyn sydd wedi newid.

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

Mae'r Storfa yn cael ei chwistrellu fel EnvironmentObject pan fydd y rhaglen yn cychwyn ac yna mae'n hygyrch mewn unrhyw olwg gan ddefnyddio @EnvironmentObject. Nid oes cosb perfformiad oherwydd bod eiddo deilliadol yn cael eu hadfer yn gyflym neu eu cyfrifo o gyflwr y cais.

Mae'r cod uchod yn newid y ddelwedd os bydd y poster ffilm yn newid.

Ac mae hyn yn cael ei wneud mewn gwirionedd gydag un llinell yn unig, gyda chymorth pa safbwyntiau sy'n gysylltiedig â'r wladwriaeth. Os ydych chi wedi gweithio gyda ReSwift ar iOS neu hyd yn oed cysylltu gyda React, byddwch chi'n deall hud SwiftUI.

Nawr gallwch chi geisio actifadu'r weithred a chyhoeddi'r cyflwr newydd. Dyma enghraifft fwy cymhleth.

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

Yn y cod uchod rwy'n defnyddio'r weithred .onDelete o SwiftUI ar gyfer pob IP. Mae hyn yn caniatáu i'r rhes yn y rhestr arddangos y swipe iOS arferol i'w ddileu. Felly pan fydd y defnyddiwr yn cyffwrdd â'r botwm dileu, mae'n sbarduno'r weithred gyfatebol ac yn tynnu'r ffilm o'r rhestr.

Wel, gan fod eiddo'r rhestr yn deillio o gyflwr BindableObject ac yn cael ei chwistrellu fel EnvironmentObject, mae SwiftUI yn diweddaru'r rhestr oherwydd bod ForEach yn gysylltiedig â'r eiddo cyfrifedig ffilmiau.

Dyma ran o'r lleihäwr 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
}

Gweithredir y lleihäwr pan fyddwch yn anfon gweithred ac yn dychwelyd cyflwr newydd, fel y nodir uchod.

Nid af i fanylion eto - sut mae SwiftUI mewn gwirionedd yn gwybod beth i'w arddangos. Er mwyn deall hyn yn ddyfnach, mae'n werth gweld sesiwn WWDC ar lif data yn SwiftUI. Mae hefyd yn esbonio'n fanwl pam a phryd i'w ddefnyddio wladwriaeth, @Rhwymo , ObjectBinding ac EnvironmentObject .

Mae Skillsbox yn argymell:

Ffynhonnell: hab.com

Ychwanegu sylw