Applikatioun Entwécklung op SwiftUI. Deel 1: Dataflow a Redux

Applikatioun Entwécklung op SwiftUI. Deel 1: Dataflow a Redux

Nodeems ech an der State of the Union Sessioun um WWDC 2019 deelgeholl hunn, hunn ech beschloss en déif Tauchen an SwiftUI ze maachen. Ech hu vill Zäit domat geschafft an hunn elo ugefaang eng richteg Applikatioun z'entwéckelen déi fir eng breet Palette vu Benotzer nëtzlech ka sinn.

Ech hunn et MovieSwiftUI genannt - dëst ass eng App fir nei an al Filmer ze sichen, souwéi se an enger Sammlung ze sammelen mat TMDB API. Ech hunn ëmmer Filmer gär a souguer eng Firma erstallt déi an dësem Beräich schafft, och wann et viru laanger Zäit ass. D'Firma konnt kaum cool genannt ginn, awer d'Applikatioun war!

Mir erënneren Iech: fir all Habr Lieser - eng Remise vun 10 Rubel wann Dir Iech an all Skillbox Cours aschreift mat dem Habr Promo Code.

Skillbox recommandéiert: Online pädagogesch Cours "Beruff Java Entwéckler".

Also wat kann MovieSwiftUI maachen?

  • Interagéiert mat der API - bal all modern Applikatioun mécht dat.
  • Lued asynchron Daten op Ufroen a parséiert JSON an de Swift Modell benotzt Kodéierbar.
  • Weist Biller op Ufro gelueden a cache se.
  • Dës App fir iOS, iPadOS a macOS bitt déi bescht UX fir Benotzer vun dësen OSen.
  • De Benotzer kann Daten generéieren an hir eege Filmlëschten erstellen. D'Applikatioun späichert a restauréiert Benotzerdaten.
  • Meenungen, Komponenten a Modeller sinn kloer mat dem Redux Muster getrennt. Den Datefloss hei ass unidirektional. Et kann komplett cache, restauréiert an iwwerschriwwe ginn.
  • D'Applikatioun benotzt d'Basiskomponente vu SwiftUI, TabbedView, SegmentedControl, NavigationView, Form, Modal, etc. Et bitt och personaliséiert Meenungen, Gesten, UI / UX.

Applikatioun Entwécklung op SwiftUI. Deel 1: Dataflow a Redux
Tatsächlech ass d'Animatioun glat, de GIF huet e bëssen ruckend erausgestallt

D'Aarbecht un der App huet mir vill Erfahrung ginn an allgemeng war et eng positiv Erfahrung. Ech konnt eng voll funktionell Applikatioun schreiwen, am September wäert ech se verbesseren an am AppStore publizéieren, gläichzäiteg mat der Verëffentlechung vum iOS 13.

Redux, BindableObject an EnvironmentObject

Applikatioun Entwécklung op SwiftUI. Deel 1: Dataflow a Redux

Ech schaffe schonn zanter ronn zwee Joer mat Redux, also sinn ech relativ gutt dran. Besonnesch benotzen ech et am Frontend fir reagéieren Websäit, wéi och fir nativ iOS (Swift) an Android (Kotlin) Uwendungen z'entwéckelen.

Ech hunn ni bedauert datt ech Redux als Dateflossarchitektur gewielt hunn fir eng SwiftUI Applikatioun ze bauen. Déi schwieregst Deeler wann Dir Redux an enger UIKit App benotzt, schaffe mam Buttek a kréien an zréckzéien Daten a kartéieren se op Är Meenungen / Komponenten. Fir dëst ze maachen, hunn ech eng Zort Bibliothéik vu Connectoren ze kreéieren (mat ReSwift a ReKotlin). Wierker gutt, awer zimlech vill Code. Leider ass et (nach) net Open Source.

Gutt Noriicht! Déi eenzeg Saache fir Iech mat SwiftUI Suergen ze maachen - wann Dir plangt Redux ze benotzen - sinn Geschäfter, Staaten a Reduzéierer. Interaktioun mam Geschäft gëtt komplett vu SwiftUI versuergt dank @EnvironmentObject. Also, Geschäft fänkt mat engem BindableObject un.

Ech hunn en einfache Swift Package erstallt, SwiftUIFlux, déi Basisverbrauch vu Redux ubitt. A mengem Fall ass et Deel vum MovieSwiftUI. ech och geschriwwen e Schrëtt fir Schrëtt Tutorial, déi Iech hëllefen dës Komponent ze benotzen.

Wéi heescht et schaffen?

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

All Kéier wann Dir eng Aktioun ausléist, aktivéiert Dir d'Gearbox. Et wäert Aktiounen no dem aktuellen Zoustand vun der Applikatioun evaluéieren. Et gëtt dann en neie geännerten Zoustand am Aklang mat der Aktiounstyp an Daten zréck.

Gutt, well de Buttek e BindableObject ass, wäert et de SwiftUI informéieren wann säi Wäert ännert mat der willChange Eegeschafte geliwwert vum PassthroughSubject. Dëst ass well de BindableObject e PublisherType muss ubidden, awer d'Protokollimplementatioun ass verantwortlech fir et ze managen. Am Allgemengen ass dëst e ganz mächtegt Tool vun Apple. Deementspriechend, am nächste Rendering-Zyklus hëlleft SwiftUI de Kierper vun de Meenungen no der Staatsännerung.

Eigentlech ass dëst all d'Häerz an d'Magie vu SwiftUI. Elo, an all Vue, déi op e Staat abonnéiert, gëtt d'Vue ofgeliwwert no wat fir Daten vum Staat kritt ginn a wat geännert huet.

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

De Store gëtt als EnvironmentObject injizéiert wann d'Applikatioun ufänkt an ass dann zougänglech an all Vue mat @EnvironmentObject. Et gëtt keng Leeschtung Eelefmeter well ofgeleet Eegeschafte séier zréckgewonnen oder aus Applikatioun Staat berechent ginn.

De Code uewen ännert d'Bild wann de Filmaffiche ännert.

An dat geschitt eigentlech just mat enger Linn, mat der Hëllef vun där Meenungen un de Staat verbonne sinn. Wann Dir mat ReSwift op iOS geschafft hutt oder souguer konnektéieren mat React, Dir wäert d'Magie vun SwiftUI verstoen.

Elo kënnt Dir probéieren d'Aktioun ze aktivéieren an den neie Staat ze publizéieren. Hei ass e méi komplext Beispill.

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

Am Code hei uewen benotzen ech d'.onDelete-Aktioun vu SwiftUI fir all IP. Dëst erlaabt d'Zeil an der Lëscht den normale iOS Swipe ze weisen fir ze läschen. Also wann de Benotzer de Läschen Knäppche beréiert, dréit et déi entspriechend Aktioun aus an läscht de Film aus der Lëscht.

Gutt, well d'Lëschteigenschaften ofgeleet ass vum BindableObject Staat an als EnvironmentObject injizéiert gëtt, aktualiséiert SwiftUI d'Lëscht well ForEach ass mat de Filmer berechent Eegeschafte verbonnen.

Hei ass en Deel vum MoviesState Reduzéierer:

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
}

De Reduzéierer gëtt ausgefouert wann Dir eng Handlung verschéckt an en neie Staat zréckkënnt, wéi uewen uginn.

Ech wäert nach net an den Detail goen - wéi SwiftUI tatsächlech weess wat ze weisen. Fir dëst méi déif ze verstoen, ass et derwäert Vue WWDC Sëtzung op Daten Flux an SwiftUI. Et erkläert och am Detail firwat a wéini ze benotzen Stat, @Binding, ObjectBinding an EnvironmentObject.

Skillbox recommandéiert:

Source: will.com

Setzt e Commentaire