Rakenduse arendamine SwiftUI-s. Osa 1: andmevoog ja Redux

Rakenduse arendamine SwiftUI-s. Osa 1: andmevoog ja Redux

PĂ€rast osalemist WWDC 2019 State of the Union sessioonis otsustasin pĂ”hjalikult uurida SwiftUI-d. Olen selle kallal palju aega veetnud ja nĂŒĂŒd olen alustanud reaalse rakenduse arendamist, mis vĂ”ib olla kasulik laiale kasutajaskonnale.

Nimetasin selle MovieSwiftUI-ks — see on rakendus uute ja vanade filmide otsimiseks ning nende kogumiseks kollektsiooni kaudu TMDB API. Olen alati armastanud filme ja isegi loonud ettevĂ”tte, mis tegutseb selles valdkonnas, kuigi see oli juba ammu. EttevĂ”tet oli raske nimetada Ă€gedaks, aga rakendust kĂŒll!

Tuletame meelde: kĂ”igile «Habr» lugejatele – 10 000 rubla allahindlus igale Skillboxi kursusele, kasutades sooduskoodi «Habr».

Skillbox soovitab: Haridusalane veebikursus «Java-arendaja amet».

Nii et, mida MovieSwiftUI suudab?

  • Seda integreeritakse API-ga — seda teeb peaaegu iga kaasaegne rakendus.
  • See laadib asĂŒnkroonselt andmeid pĂ€ringute kaudu ja parsib JSON-i Swift mudelitesse, kasutades Codable.
  • NĂ€itab pilte, mis on nĂ”udmisel laaditud ja vahemĂ€lustatu.
  • See rakendus iOS, iPadOS ja macOS platvormidele tagab parima kasutajakogemuse nende operatsioonisĂŒsteemide kasutajatele.
  • Kasutaja saab genereerida andmeid, luua oma filmide loendeid. Rakendus salvestab ja taastab kasutajate andmed.
  • Vaated, komponendid ja mudelid on selgelt eraldatud Redux-mustriga. Andmevoog on siin ĂŒhesuunaline. Seda saab tĂ€ielikult vahemĂ€lustada, taastada ja ĂŒmber kirjutada.
  • Rakendus kasutab pĂ”hilisi SwiftUI komponente, sealhulgas TabbedView, SegmentedControl, NavigationView, Form, Modal jne. Samuti tagab see kohandatud vaated, ĆŸestid, UI/UX.

Rakenduse arendamine SwiftUI-s. Osa 1: andmevoog ja Redux
Tegelikult on animatsioon sujuv, kuid gif on natuke hĂŒplev.

Rakenduse arendamine andis mulle palju kogemusi ja tervikuna oli see positiivne kogemus. Suutsin kirjutada tÀisfunktsionaalse rakenduse, mille parandan ja laon AppStore'i septembriks koos iOS 13.VÀljalaskega.

Redux, BindableObject ja EnvironmentObject

Rakenduse arendamine SwiftUI-s. Osa 1: andmevoog ja Redux

KÀesoleval hetkel olen töötanud Reduxiga juba umbes kaks aastat, seega mÔistan seda suhteliselt hÀsti. EelkÔige kasutan seda oma veebilehe frontendis React , samuti kohalike iOS (Swift) ja Android (Kotlin) rakenduste arendamiseks.

Ma ei ole kordagi kahetsenud, et valisin Reduxi andmevoo arhitektuuriks SwiftUI rakenduse loomisel. KĂ”ige keerulisemad hetked Reduxi kasutamisel UIKit rakenduses on tööstore'iga, samuti andmete saamine ja vĂ€ljatoomine ning nende sidumine teie vaadete / komponentidega. Selle jaoks pidin looma omamoodi konnektorite teegi (ReSwift ja ReKotlin). See töötab hĂ€sti, kuid koodi on ĂŒsna palju. Kahjuks ei ole see (veel) avatud lĂ€htekoodiga.

Hea uudis! Ainus, mille pĂ€rast tasub SwiftUI puhul muretseda, on see, kui plaanite kasutada Reduxi — store, olekud ja reducerid. SwiftUI hoolitseb store'i interaktsiooni tĂ€ielikult @EnvironmentObject'i kaudu. Nii algab store BindableObject'iga.

Ma lÔin lihtsa Swift paketi, SwiftUIFlux, mis tagab Reduxi pÔhikasutuse. Minu puhul on see osa MovieSwiftUI-st. Samuti olen kirjutanud samm-sammult Ôpetuse, mis aitab seda komponenti kasutada.

Kuidas see töötab?

final public class Store: BindableObject {
    public let willChange = PassthroughSubject()
        
    private(set) public var state: State
    
    private func _dispatch(action: Action) {
        willChange.send()
        state = reducer(state, action)
    }
}

Iga kord, kui kĂ€ivitate tegevuse, aktiveerite redutseerija. See hindab tegevusi vastavalt rakenduse praegusele olekule. Talle jĂ€rgneb uue muudetud oleku tagastamine vastavalt tegevuse tĂŒĂŒbile ja andmetele.

Ja kuna store on BindableObject, teavitab ta SwiftUI-d oma vÀÀrtuse muutumisest, kasutades willChange'i omadust, mille pakub PassthroughSubject. See on nii, kuna BindableObject peab pakkuma PublisherType'i, kuid protokolli elluviimine vastutab selle haldamise eest. Üldiselt on see Apple'i vĂ€ga vĂ”imas tööriist. Vastavalt sellele aitab SwiftUI jĂ€rgmises renderdamise tsĂŒklis kuvada vaadete keha oleku muutumise jĂ€rgi.

Sisuliselt on see kĂ”ik — SwiftUI sĂŒda ja maagia. NĂŒĂŒd igas vaates, mis on registreeritud oleku jĂ€rgi, kuvatakse vaade vastavalt andmetele, mis on saadud olekust ja mis on muutunud.

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

Store on tÔuk objektina rakenduse kÀivitamisel ja seejÀrel on see saadaval igas vaates @EnvironmentObject abil. TÔhusus ei kannata, kuna tuletatud omadused ekstraheeritakse vÔi arvutatakse rakenduse olekust kiiresti.

Ülaltoodud kood muudab pilti, kui filmi plakat muutub.

Ja see toimub tegelikult vaid ĂŒhe reaga, millega seotakse vaated olekuga. Kui olete töötanud ReSwiftiga iOS-is vĂ”i isegi connect Reactis, mĂ”istate, mis on SwiftUI vĂ”lu.

NĂŒĂŒd saab proovida aktiveerida toimingut ja avaldada uut olekut. Siin on keerulisem nĂ€ide.

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

Ülaltoodud koodis kasutan SwiftUI-s iga IP jaoks tegevust .onDelete. See vĂ”imaldab loendi real nĂ€idata tavalist iOS-i pĂŒhkimisfunktsiooni kustutamiseks. Seega, kui kasutaja puudutab kustutamisnuppu, kĂ€ivitab ta vastava tegevuse ja eemaldab filmi loendist.

Kuna loendi omadus on tuletatud BindableObject olekust ja see on sisestatud kui EnvironmentObject, vÀrskendab SwiftUI loendit, kuna ForEach on seotud arvutatava omadusega movies.

Siin on osa reducerist 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
}

Reduktor töötab, kui saadate tegevuse ja tagastab uue oleku, nagu eespool öeldud.

Ma ei hakka veel detailidesse laskuma — kust Swifti UI tegelikult teab, mida kuvada. Selle pĂ”hjalikumaks mĂ”istmiseks tasub vaadata WWDC sessiooni andmevoogudest Swifti UI-s. Samuti rÀÀgitakse seal ĂŒksikasjalikult, miks ja millal kasutada State, @Binding, ObjectBinding ja EnvironmentObject.

Skillbox soovitab:

Allikas: habr.com

Osta usaldusvÀÀrne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid | ProHoster