Żvilupp ta' applikazzjoni fuq SwiftUI. Parti 1: Dataflow u Redux

Żvilupp ta' applikazzjoni fuq SwiftUI. Parti 1: Dataflow u Redux

Wara li attendejt is-sessjoni tal-Istat tal-Unjoni fil-WWDC 2019, iddeċidejt li ngħaddas fil-fond fis-SwiftUI. Għamilt ħafna ħin naħdem magħha u issa bdejt niżviluppa applikazzjoni reali li tista’ tkun utli għal firxa wiesgħa ta’ utenti.

Sejjaħt MovieSwiftUI - din hija app għat-tiftix għal films ġodda u qodma, kif ukoll biex tiġborhom f'kollezzjoni bl-użu TMDB API. Dejjem ħabbejt il-films u saħansitra ħloqt kumpanija li taħdem f’dan il-qasam, għalkemm żmien twil ilu. Il-kumpanija ma tantx setgħet tissejjaħ cool, iżda l-applikazzjoni kienet!

Infakkrukom: għall-qarrejja kollha ta '"Habr" - skont ta' 10 rublu meta tirreġistra fi kwalunkwe kors ta 'Skillbox billi tuża l-kodiċi promozzjonali "Habr".

Skillbox jirrakkomanda: Kors edukattiv onlajn "Professjoni Java Developer".

Allura x'jista' jagħmel MovieSwiftUI?

  • Tinteraġixxi mal-API - kważi kull applikazzjoni moderna tagħmel dan.
  • Tgħabbi dejta asinkronika dwar it-talbiet u teżamina JSON fil-mudell Swift bl-użu Kodifikabbli.
  • Juri immaġini mgħobbija fuq talba u jżommhom fil-caches.
  • Din l-app għal iOS, iPadOS, u macOS tipprovdi l-aħjar UX għall-utenti ta’ dawn l-OS.
  • L-utent jista 'jiġġenera data u joħloq il-listi tal-films tiegħu stess. L-applikazzjoni tiffranka u tirrestawra d-dejta tal-utent.
  • Il-veduti, il-komponenti u l-mudelli huma separati b'mod ċar bl-użu tal-mudell Redux. Il-fluss tad-dejta hawnhekk huwa unidirezzjonali. Jista 'jiġi kompletament fil-cache, restawrat u miktub fuqu.
  • L-applikazzjoni tuża l-komponenti bażiċi ta 'SwiftUI, TabbedView, SegmentedControl, NavigationView, Form, Modal, eċċ. Jipprovdi wkoll veduti personalizzati, ġesti, UI/UX.

Żvilupp ta' applikazzjoni fuq SwiftUI. Parti 1: Dataflow u Redux
Fil-fatt, l-animazzjoni hija bla xkiel, il-GIF irriżulta ftit jerky

Il-ħidma fuq l-app tani ħafna esperjenza u b'mod ġenerali kienet esperjenza pożittiva. Stajt nikteb applikazzjoni kompletament funzjonali, f'Settembru ser intejjebha u nippubblikaha fl-AppStore, fl-istess ħin mar-rilaxx ta' iOS 13.

Redux, BindableObject u EnvironmentObject

Żvilupp ta' applikazzjoni fuq SwiftUI. Parti 1: Dataflow u Redux

Ilni naħdem ma' Redux għal madwar sentejn issa, għalhekk jien relattivament kapaċi sew fiha. B'mod partikolari, nużaha fil-frontend għal Irreaġixxi websajt, kif ukoll għall-iżvilupp ta’ applikazzjonijiet indiġeni ta’ iOS (Swift) u Android (Kotlin).

Qatt ma ddispjaċini li għażilt Redux bħala l-arkitettura tal-fluss tad-dejta għall-bini ta 'applikazzjoni SwiftUI. L-aktar partijiet ta’ sfida meta tuża Redux f’app UIKit qed jaħdmu mal-maħżen u jġibu u jġibu d-dejta u jimmappjawha mal-fehmiet/komponenti tiegħek. Biex tagħmel dan, kelli noħloq tip ta 'librerija ta' konnetturi (bl-użu ta 'ReSwift u ReKotlin). Jaħdem tajjeb, iżda pjuttost ħafna kodiċi. Sfortunatament, mhuwiex (għadu) sors miftuħ.

Aħbar tajba! L-uniċi affarijiet li għandek tinkwieta dwar SwiftUI - jekk qed tippjana li tuża Redux - huma l-ħwienet, l-istati u r-reducers. L-interazzjoni mal-maħżen hija kompletament ikkurata minn SwiftUI grazzi għal @EnvironmentObject. Allura, il-maħżen jibda b'BindableObject.

Ħloqt pakkett Swift sempliċi, SwiftUIFlux, li jipprovdi użu bażiku ta' Redux. Fil-każ tiegħi huwa parti minn MovieSwiftUI. Jien ukoll kiteb tutorja pass pass, li tgħinek tuża dan il-komponent.

Kif taħdem?

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

Kull darba li tiskatta azzjoni, tattiva l-gearbox. Se tevalwa l-azzjonijiet skont l-istat attwali tal-applikazzjoni. Imbagħad se jirritorna stat modifikat ġdid skont it-tip ta 'azzjoni u d-dejta.

Ukoll, peress li l-maħżen huwa BindableObject, jinnotifika lil SwiftUI meta l-valur tiegħu jinbidel billi juża l-proprjetà willChange ipprovduta minn PassthroughSubject. Dan għaliex il-BindableObject għandu jipprovdi PublisherType, iżda l-implimentazzjoni tal-protokoll hija responsabbli għall-ġestjoni tiegħu. B'mod ġenerali, din hija għodda qawwija ħafna minn Apple. Għaldaqstant, fiċ-ċiklu ta 'rendi li jmiss, SwiftUI se jgħin biex jirrendi l-korp tal-fehmiet skont il-bidla tal-istat.

Fil-fatt, din hija l-qalba u l-maġija kollha ta 'SwiftUI. Issa, fi kwalunkwe ħsieb li jissottoskrivi għal stat, il-veduta se tingħata skond liema data tiġi riċevuta mill-istat u dak li nbidel.

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

Il-Aħżen jiġi injettat bħala EnvironmentObject meta tibda l-applikazzjoni u mbagħad ikun aċċessibbli fi kwalunkwe viżjoni bl-użu ta' @EnvironmentObject. M'hemm l-ebda penali tal-prestazzjoni minħabba li l-proprjetajiet derivati ​​jiġu rkuprati jew ikkalkulati malajr mill-istat tal-applikazzjoni.

Il-kodiċi ta 'hawn fuq jibdel l-immaġni jekk il-poster tal-film jinbidel.

U dan fil-fatt isir b'linja waħda biss, li bl-għajnuna tagħha l-opinjonijiet huma konnessi mal-istat. Jekk ħdimt ma' ReSwift fuq iOS jew saħansitra jgħaqqdu ma 'React, int ser tifhem il-maġija ta' SwiftUI.

Issa tista 'tipprova tattiva l-azzjoni u tippubblika l-istat il-ġdid. Hawn eżempju aktar kumpless.

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

Fil-kodiċi ta 'hawn fuq, qed nuża l-azzjoni .onDelete minn SwiftUI għal kull IP. Dan jippermetti li r-ringiela fil-lista turi l-iSwipe normali tal-iOS biex tħassar. Allura meta l-utent imiss il-buttuna tħassar, iqajjem l-azzjoni korrispondenti u jneħħi l-film mil-lista.

Ukoll, peress li l-proprjetà tal-lista hija derivata mill-istat BindableObject u hija injettata bħala EnvironmentObject, SwiftUI taġġorna l-lista minħabba li ForEach hija assoċjata mal-proprjetà kkalkulata tal-films.

Hawn parti mir-reducer 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
}

Ir-reducer jiġi esegwit meta tibgħat azzjoni u tirritorna stat ġdid, kif intqal hawn fuq.

Għadni mhux se nidħol fid-dettall - kif SwiftUI fil-fatt jaf x'għandu juri. Biex tifhem dan aktar fil-fond, ta 'min ara sessjoni tal-WWDC dwar il-fluss tad-dejta fi SwiftUI. Jispjega wkoll fid-dettall għaliex u meta tuża Istat, @Binding, ObjectBinding u EnvironmentObject.

Skillbox jirrakkomanda:

Sors: www.habr.com

Żid kumment