Lietojumprogrammu izstrāde SwiftUI. 1. daļa: datu plūsma un redux

Lietojumprogrammu izstrāde SwiftUI. 1. daļa: datu plūsma un redux

Pēc piedalÄ«Å”anās sesijā ā€œState of the Unionā€ WWDC 2019 es nolēmu dziļi izpētÄ«t SwiftUI. Esmu pavadÄ«jis daudz laika, strādājot ar to, un tagad esmu sācis izstrādāt reālu aplikāciju, kas var bÅ«t noderÄ«ga plaÅ”am lietotāju lokam.

Es to nosaucu par MovieSwiftUI ā€” Ŕī ir lietotne jaunu un vecu filmu meklÄ“Å”anai, kā arÄ« to apkopoÅ”anai kolekcijā, izmantojot TMDB API. Man vienmēr ir patikuÅ”as filmas un pat izveidoju uzņēmumu, kas strādā Å”ajā jomā, lai gan jau sen. Kompāniju diez vai varētu nosaukt par forÅ”u, bet pieteikums gan!

Atgādinām: visiem "Habr" lasītājiem - atlaide 10 000 rubļu, reģistrējoties jebkurā Skillbox kursā, izmantojot "Habr" reklāmas kodu.

Skillbox iesaka: IzglītojoŔs tieŔsaistes kurss "Java izstrādātāja profesija".

Tātad, ko MovieSwiftUI var darīt?

  • Mijiedarbojas ar API ā€” to dara gandrÄ«z jebkura moderna lietojumprogramma.
  • Ielādē asinhronos datus par pieprasÄ«jumiem un parsē JSON Swift modelÄ«, izmantojot Kodējams.
  • Parāda pēc pieprasÄ«juma ielādētos attēlus un saglabā tos keÅ”atmiņā.
  • Å Ä« iOS, iPadOS un macOS lietotne nodroÅ”ina vislabāko UX Å”o operētājsistēmu lietotājiem.
  • Lietotājs var Ä£enerēt datus un izveidot savus filmu sarakstus. Lietojumprogramma saglabā un atjauno lietotāja datus.
  • Skati, komponenti un modeļi ir skaidri atdalÄ«ti, izmantojot Redux modeli. Datu plÅ«sma Å”eit ir vienvirziena. To var pilnÄ«bā saglabāt keÅ”atmiņā, atjaunot un pārrakstÄ«t.
  • Lietojumprogramma izmanto SwiftUI, TabbedView, SegmentedControl, NavigationView, Form, Modal u.c. pamatkomponentus. Tas nodroÅ”ina arÄ« pielāgotus skatus, žestus, UI/UX.

Lietojumprogrammu izstrāde SwiftUI. 1. daļa: datu plūsma un redux
Patiesībā animācija ir gluda, GIF izrādījās nedaudz saraustīts

Darbs pie lietotnes man deva lielu pieredzi, un kopumā tā bija pozitÄ«va pieredze. Paspēju uzrakstÄ«t pilnÄ«bā funkcionējoÅ”u aplikāciju, septembrÄ« to uzlaboÅ”u un publicÄ“Å”u AppStore, vienlaikus ar iOS 13 iznākÅ”anu.

Redux, BindableObject un EnvironmentObject

Lietojumprogrammu izstrāde SwiftUI. 1. daļa: datu plūsma un redux

Es strādāju ar Redux jau apmēram divus gadus, tāpēc esmu salÄ«dzinoÅ”i labi pārzinājis to. Jo Ä«paÅ”i es to izmantoju priekÅ”galā Reaģēt vietnei, kā arÄ« vietējo iOS (Swift) un Android (Kotlin) lietojumprogrammu izstrādei.

Es nekad neesmu nožēlojis, ka izvēlējos Redux kā datu plÅ«smas arhitektÅ«ru SwiftUI lietojumprogrammas izveidei. Sarežģītākās daļas, izmantojot Redux UIKit lietotnē, ir darbs ar veikalu, datu iegÅ«Å”ana un izguve un to kartÄ“Å”ana ar saviem skatiem/komponentiem. Lai to izdarÄ«tu, man bija jāizveido sava veida savienotāju bibliotēka (izmantojot ReSwift un ReKotlin). Darbojas labi, bet diezgan daudz koda. Diemžēl tas (vēl) nav atvērts avots.

Labas ziņas! VienÄ«gās lietas, par kurām jāuztraucas saistÄ«bā ar SwiftUI ā€” ja plānojat izmantot Redux ā€” ir veikali, Å”tati un reduktori. Pateicoties @EnvironmentObject, par mijiedarbÄ«bu ar veikalu pilnÄ«bā rÅ«pējas SwiftUI. Tātad, veikals sākas ar BindableObject.

Es izveidoju vienkārÅ”u Swift pakotni, SwiftUIFlux, kas nodroÅ”ina pamata Redux lietoÅ”anu. Manā gadÄ«jumā tā ir daļa no MovieSwiftUI. ES arÄ« uzrakstÄ«ja soli pa solim apmācÄ«bu, kas palÄ«dzēs izmantot Å”o komponentu.

Kā tas strādā?

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

Katru reizi, kad aktivizējat darbÄ«bu, jÅ«s aktivizējat pārnesumkārbu. Tas novērtēs darbÄ«bas atbilstoÅ”i lietojumprogrammas paÅ”reizējam stāvoklim. Pēc tam tas atgriezÄ«s jaunu modificētu stāvokli atbilstoÅ”i darbÄ«bas veidam un datiem.

Tā kā veikals ir BindableObject, tas paziņos SwiftUI, kad tā vērtÄ«ba mainÄ«sies, izmantojot PassthroughSubject nodroÅ”ināto rekvizÄ«tu willChange. Tas ir tāpēc, ka BindableObject ir jānodroÅ”ina PublisherType, bet protokola ievieÅ”ana ir atbildÄ«ga par tā pārvaldÄ«bu. Kopumā tas ir ļoti spēcÄ«gs Apple rÄ«ks. AttiecÄ«gi nākamajā renderÄ“Å”anas ciklā SwiftUI palÄ«dzēs atveidot skatu pamattekstu atbilstoÅ”i stāvokļa izmaiņām.

PatiesÄ«bā Ŕī ir visa SwiftUI sirds un burvÄ«ba. Tagad jebkurā skatā, kas abonē stāvokli, skats tiks atveidots atkarÄ«bā no tā, kādi dati ir saņemti no valsts un kas ir mainÄ«jies.

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

Veikals tiek ievadīts kā EnvironmentObject, kad lietojumprogramma tiek startēta, un pēc tam ir pieejams jebkurā skatā, izmantojot @EnvironmentObject. Nav veiktspējas soda, jo atvasinātie rekvizīti tiek ātri izgūti vai aprēķināti no lietojumprogrammas stāvokļa.

IepriekÅ” minētais kods maina attēlu, ja mainās filmas plakāts.

Un tas faktiski tiek darīts tikai ar vienu līniju, ar kuras palīdzību viedokļi tiek savienoti ar valsti. Ja esat strādājis ar ReSwift operētājsistēmā iOS vai pat savienot ar React jūs sapratīsit SwiftUI burvību.

Tagad varat mēģināt aktivizēt darbību un publicēt jauno stāvokli. Šeit ir sarežģītāks piemērs.

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

IepriekÅ” minētajā kodā katrai IP izmantoju darbÄ«bu .onDelete no SwiftUI. Tas ļauj saraksta rindā parādÄ«t parasto iOS velciet, lai dzēstu. Tātad, kad lietotājs pieskaras dzÄ“Å”anas pogai, tas aktivizē atbilstoÅ”o darbÄ«bu un noņem filmu no saraksta.

Tā kā saraksta rekvizīts ir iegūts no BindableObject stāvokļa un tiek ievadīts kā EnvironmentObject, SwiftUI atjaunina sarakstu, jo ForEach ir saistīts ar filmu aprēķināto rekvizītu.

Šeit ir daļa no MoviesState reduktora:

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
}

Samazinātājs tiek izpildÄ«ts, kad nosÅ«tāt darbÄ«bu un atgriežat jaunu stāvokli, kā minēts iepriekÅ”.

Es vēl neiedziļināŔos - kā SwiftUI patiesÄ«bā zina, ko parādÄ«t. Lai to saprastu dziļāk, ir vērts skatÄ«t WWDC sesiju par datu plÅ«smu SwiftUI. Tajā arÄ« detalizēti paskaidrots, kāpēc un kad to lietot Valsts, @Binding, ObjectBinding un EnvironmentObject.

Skillbox iesaka:

Avots: www.habr.com

Pievieno komentāru