Ukuzaji wa programu kwenye SwiftUI. Sehemu ya 1: Utiririshaji wa data na Redux

Ukuzaji wa programu kwenye SwiftUI. Sehemu ya 1: Utiririshaji wa data na Redux

Baada ya kuhudhuria kikao cha Jimbo la Muungano katika WWDC 2019, niliamua kupiga mbizi ndani ya SwiftUI. Nimetumia muda mwingi kufanya kazi nayo na sasa nimeanza kutengeneza programu halisi ambayo inaweza kuwa na manufaa kwa watumiaji mbalimbali.

Niliiita MovieSwiftUI - hii ni programu ya kutafuta filamu mpya na za zamani, na pia kukusanya katika mkusanyiko kwa kutumia. TMDB API. Siku zote nimependa filamu na hata kuunda kampuni inayofanya kazi katika uwanja huu, ingawa muda mrefu uliopita. Kampuni haikuweza kuitwa nzuri, lakini maombi yalikuwa!

Tunakukumbusha: kwa wasomaji wote wa "Habr" - punguzo la rubles 10 wakati wa kujiandikisha katika kozi yoyote ya Skillbox kwa kutumia msimbo wa uendelezaji wa "Habr".

Skillbox inapendekeza: Kozi ya elimu mtandaoni "Msanidi programu wa Java".

Kwa hivyo MovieSwiftUI inaweza kufanya nini?

  • Huingiliana na API - karibu programu yoyote ya kisasa hufanya hivi.
  • Hupakia data ya asynchronous kwenye maombi na kuchanganua JSON kwenye modeli ya Swift kwa kutumia Inaweza kushikamana.
  • Huonyesha picha zilizopakiwa kwa ombi na kuzihifadhi.
  • Programu hii ya iOS, iPadOS, na macOS hutoa UX bora kwa watumiaji wa OS hizi.
  • Mtumiaji anaweza kutoa data na kuunda orodha zao za filamu. Programu huhifadhi na kurejesha data ya mtumiaji.
  • Mionekano, vijenzi na miundo imetenganishwa kwa uwazi kwa kutumia mchoro wa Redux. Mtiririko wa data hapa ni wa mwelekeo mmoja. Inaweza kuhifadhiwa kikamilifu, kurejeshwa na kuandikwa tena.
  • Programu hutumia vipengele vya msingi vya SwiftUI, TabbedView, SegmentedControl, NavigationView, Form, Modal, n.k. Pia hutoa maoni maalum, ishara, UI/UX.

Ukuzaji wa programu kwenye SwiftUI. Sehemu ya 1: Utiririshaji wa data na Redux
Kwa kweli, uhuishaji ni laini, GIF iligeuka kidogo

Kufanya kazi kwenye programu kulinipa uzoefu mwingi na kwa ujumla ilikuwa uzoefu mzuri. Niliweza kuandika programu inayofanya kazi kikamilifu, mnamo Septemba nitaiboresha na kuichapisha kwenye AppStore, wakati huo huo na kutolewa kwa iOS 13.

Redux,BindableObject na EnvironmentObject

Ukuzaji wa programu kwenye SwiftUI. Sehemu ya 1: Utiririshaji wa data na Redux

Nimekuwa nikifanya kazi na Redux kwa takriban miaka miwili sasa, kwa hivyo ninaifahamu vizuri. Hasa, mimi kutumia katika frontend kwa Tenda tovuti, na pia kwa kukuza programu asilia za iOS (Swift) na Android (Kotlin).

Sijawahi kujuta kuchagua Redux kama usanifu wa mtiririko wa data wa kujenga programu ya SwiftUI. Sehemu zenye changamoto nyingi unapotumia Redux katika programu ya UIKit ni kufanya kazi na duka na kupata na kurejesha data na kuipanga kulingana na maoni/vijenzi vyako. Ili kufanya hivyo, nilipaswa kuunda aina ya maktaba ya viunganisho (kwa kutumia ReSwift na ReKotlin). Inafanya kazi vizuri, lakini nambari nyingi sana. Kwa bahati mbaya, sio (bado) chanzo wazi.

Habari njema! Mambo pekee ya kuwa na wasiwasi kuhusu SwiftUI - ikiwa unapanga kutumia Redux - ni maduka, majimbo na vipunguzi. Mwingiliano na duka hutunzwa kabisa na SwiftUI shukrani kwa @EnvironmentObject. Kwa hivyo, duka huanza na BindableObject.

Niliunda kifurushi rahisi cha Swift, SwiftUIFlux, ambayo hutoa matumizi ya kimsingi ya Redux. Kwa upande wangu ni sehemu ya MovieSwiftUI. Mimi pia aliandika somo la hatua kwa hatua, ambayo itakusaidia kutumia sehemu hii.

Jinsi gani kazi?

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

Kila wakati unapoanzisha kitendo, unawasha kisanduku cha gia. Itatathmini vitendo kulingana na hali ya sasa ya programu. Kisha itarejesha hali mpya iliyorekebishwa kwa mujibu wa aina ya kitendo na data.

Kweli, kwa kuwa duka ni BindableObject, itaarifu SwiftUI wakati thamani yake inabadilika kwa kutumia willChange mali iliyotolewa na PassthroughSubject. Hii ni kwa sababu BindableObject lazima itoe Aina ya Mchapishaji, lakini utekelezaji wa itifaki una jukumu la kuidhibiti. Kwa ujumla, hii ni zana yenye nguvu sana kutoka kwa Apple. Ipasavyo, katika mzunguko unaofuata wa uwasilishaji, SwiftUI itasaidia kutoa maoni mengi kulingana na mabadiliko ya serikali.

Kwa kweli, huu ni moyo na uchawi wote wa SwiftUI. Sasa, kwa mtazamo wowote unaojiandikisha kwa hali, mtazamo utatolewa kulingana na data iliyopokelewa kutoka kwa serikali na nini kimebadilika.

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

Duka hudungwa kama EnvironmentObject wakati programu inapoanza na inaweza kupatikana kwa mwonekano wowote kwa kutumia @EnvironmentObject. Hakuna adhabu ya utendakazi kwa sababu mali zinazotokana hutolewa haraka au kukokotolewa kutoka kwa hali ya maombi.

Msimbo ulio hapo juu hubadilisha picha ikiwa bango la filamu litabadilika.

Na hii imefanywa kwa mstari mmoja tu, kwa msaada wa maoni ambayo yanaunganishwa na serikali. Ikiwa umefanya kazi na ReSwift kwenye iOS au hata kuungana ukiwa na React, utaelewa uchawi wa SwiftUI.

Sasa unaweza kujaribu kuwezesha kitendo na kuchapisha hali mpya. Hapa kuna mfano ngumu zaidi.

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

Katika msimbo ulio hapo juu, ninatumia kitendo cha .onDelete kutoka SwiftUI kwa kila IP. Hii inaruhusu safu mlalo kwenye orodha kuonyesha utelezeshaji wa kawaida wa iOS ili kufuta. Kwa hivyo mtumiaji anapogusa kitufe cha kufuta, huanzisha kitendo kinacholingana na kuondoa filamu kutoka kwenye orodha.

Naam, kwa kuwa kipengele cha orodha kimetokana na hali ya BindableObject na hudungwa kama EnvironmentObject, SwiftUI inasasisha orodha kwa sababu ForEach inahusishwa na filamu zilizokokotwa.

Hapa kuna sehemu ya kipunguzaji cha 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
}

Kipunguzaji hutekelezwa unapotuma kitendo na kurudisha hali mpya, kama ilivyoelezwa hapo juu.

Sitaingia kwa undani bado - jinsi SwiftUI inavyojua nini cha kuonyesha. Ili kuelewa hili kwa undani zaidi, inafaa tazama kipindi cha WWDC kuhusu mtiririko wa data katika SwiftUI. Pia inaelezea kwa undani kwa nini na wakati wa kutumia Hali, @Binding, ObjectBinding na EnvironmentObject.

Skillbox inapendekeza:

Chanzo: mapenzi.com

Kuongeza maoni