Pangembangan aplikasi ing SwiftUI. Part 1: Dataflow lan Redux

Pangembangan aplikasi ing SwiftUI. Part 1: Dataflow lan Redux

Sawise nekani sesi State of Union ing WWDC 2019, aku mutusake kanggo nyilem jero menyang SwiftUI. Aku wis ngginakaken akèh wektu kanggo nggarap lan saiki wis miwiti ngembangaken aplikasi nyata sing bisa migunani kanggo sawetara saka sudhut pangguna.

Aku nyebat MovieSwiftUI - iki app kanggo nggoleki film anyar lan lawas, uga ngumpulake ing koleksi nggunakake TMDB API. Aku tansah seneng film lan malah nggawe perusahaan sing kerja ing lapangan iki, sanajan wis suwe. Perusahaan meh ora bisa diarani keren, nanging aplikasi kasebut!

Kita ngelingake: kanggo kabeh sing maca "Habr" - diskon 10 rubel nalika ndhaptar kursus Skillbox nggunakake kode promosi "Habr".

Skillbox nyaranake: Kursus online pendidikan "Profesi Java Developer".

Dadi apa sing bisa ditindakake dening MovieSwiftUI?

  • Berinteraksi karo API - meh kabeh aplikasi modern nindakake iki.
  • Muat data bedo ing panjalukan lan parses JSON menyang model Swift nggunakake Bisa codable.
  • Nuduhake gambar dimuat ing panyuwunan lan caches.
  • Aplikasi iki kanggo iOS, iPadOS, lan macOS nyedhiyakake UX paling apik kanggo pangguna OS kasebut.
  • Pangguna bisa ngasilake data lan nggawe dhaptar film dhewe. Aplikasi nyimpen lan mulihake data pangguna.
  • Tampilan, komponen lan model dipisahake kanthi jelas nggunakake pola Redux. Aliran data ing kene unidirectional. Bisa disimpen kanthi lengkap, dibalekake lan ditindih.
  • Aplikasi kasebut nggunakake komponen dhasar SwiftUI, TabbedView, SegmentedControl, NavigationView, Formulir, Modal, lsp. Uga nyedhiyakake tampilan khusus, sadurunge nyeret, UI / UX.

Pangembangan aplikasi ing SwiftUI. Part 1: Dataflow lan Redux
Nyatane, animasi kasebut lancar, GIF dadi rada jerky

Nggarap app menehi akeh pengalaman lan sakabèhé iku pengalaman positif. Aku bisa nulis aplikasi kanthi fungsional, ing wulan September aku bakal nambah lan nerbitake ing AppStore, bebarengan karo rilis iOS 13.

Redux, BindableObject lan EnvironmentObject

Pangembangan aplikasi ing SwiftUI. Part 1: Dataflow lan Redux

Aku wis nggarap Redux kira-kira rong taun saiki, mula aku cukup ngerti babagan iki. Ing tartamtu, Aku nggunakake ing frontend kanggo nanggepi situs web, uga kanggo ngembangake aplikasi iOS asli (Swift) lan Android (Kotlin).

Aku ora tau getun milih Redux minangka arsitektur aliran data kanggo mbangun aplikasi SwiftUI. Bagean sing paling angel nalika nggunakake Redux ing aplikasi UIKit yaiku nggarap toko lan njupuk lan njupuk data lan pemetaan menyang tampilan / komponen. Kanggo nindakake iki, aku kudu nggawe jinis perpustakaan konektor (nggunakake ReSwift lan ReKotlin). Bisa uga, nanging cukup akeh kode. Sayange, iku durung (durung) mbukak sumber.

Kabar apik! Siji-sijine perkara sing kudu dikuwatirake karo SwiftUI - yen sampeyan arep nggunakake Redux - yaiku toko, negara, lan pengurangan. Interaksi karo toko wis rampung ditangani dening SwiftUI thanks kanggo @EnvironmentObject. Dadi, nyimpen diwiwiti karo BindableObject.

Aku nggawe paket Swift sing prasaja, SwiftUIFlux, sing nyedhiyakake panggunaan dhasar Redux. Ing kasusku, iku bagean saka MovieSwiftUI. Aku uga wis nulis tutorial step-by-step, sing bakal mbantu sampeyan nggunakake komponen iki.

Carane ora iku bisa?

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

Saben sampeyan micu tumindak, sampeyan ngaktifake gearbox. Bakal ngevaluasi tumindak miturut kahanan aplikasi saiki. Banjur bakal ngasilake negara sing diowahi anyar sesuai karo jinis tumindak lan data.

Ya, amarga toko minangka BindableObject, bakal menehi kabar marang SwiftUI nalika regane diganti nggunakake properti willChange sing diwenehake dening PassthroughSubject. Iki amarga BindableObject kudu nyedhiyani PublisherType, nanging implementasine protokol tanggung jawab kanggo ngatur. Sakabèhé, iki minangka alat sing kuat banget saka Apple. Mulane, ing siklus rendering sabanjure, SwiftUI bakal mbantu nerjemahake awak tampilan miturut owah-owahan negara.

Bener, iki kabeh ati lan sihir SwiftUI. Saiki, ing tampilan apa wae sing langganan negara, tampilan bakal ditampilake miturut data sing ditampa saka negara lan apa sing wis diganti.

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

Toko disuntikake minangka EnvironmentObject nalika aplikasi diwiwiti lan banjur bisa diakses ing sembarang tampilan nggunakake @EnvironmentObject. Ora ana paukuman kinerja amarga sifat sing diturunake kanthi cepet dijupuk utawa diwilang saka negara aplikasi.

Kode ing ndhuwur ngganti gambar yen poster film diganti.

Lan iki bener rampung karo mung siji baris, karo bantuan kang views disambungake menyang negara. Yen sampeyan wis nggarap ReSwift ing iOS utawa malah nyambung karo React, sampeyan bakal ngerti keajaiban SwiftUI.

Saiki sampeyan bisa nyoba ngaktifake tumindak lan nerbitake negara anyar. Ing ngisor iki conto sing luwih rumit.

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

Ing kode ing ndhuwur, aku nggunakake tumindak .onDelete saka SwiftUI kanggo saben IP. Iki ngidini baris ing dhaptar kanggo nampilake geser iOS normal kanggo mbusak. Dadi nalika pangguna nutul tombol mbusak, iku micu tumindak sing cocog lan mbusak film saka dhaftar.

Ya, amarga properti dhaptar kasebut asale saka negara BindableObject lan disuntikake minangka EnvironmentObject, SwiftUI nganyari dhaptar amarga ForEach digandhengake karo properti sing diwilang film.

Iki minangka bagean saka pengurangan 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
}

Reducer dieksekusi nalika sampeyan ngirim tumindak lan bali menyang negara anyar, kaya sing kasebut ing ndhuwur.

Aku ora bakal rinci - kepiye carane SwiftUI ngerti apa sing bakal ditampilake. Kanggo mangerteni iki luwih jero, iku worth ndeleng sesi WWDC ing aliran data ing SwiftUI. Uga nerangake kanthi rinci kenapa lan kapan kudu digunakake State, @Binding, ObjectBinding lan EnvironmentObject.

Skillbox nyaranake:

Source: www.habr.com

Add a comment