SwiftUI дээр програм хөгжүүлэлт. 1-р хэсэг: Dataflow ба Redux

SwiftUI дээр програм хөгжүүлэлт. 1-р хэсэг: Dataflow ба Redux

WWDC 2019-д болсон Холбооны байдлын хуралдаанд оролцсоныхоо дараа би SwiftUI-д гүнзгий орохоор шийдсэн. Би түүнтэй ажиллахад маш их цаг зарцуулсан бөгөөд одоо өргөн хүрээний хэрэглэгчдэд хэрэг болохуйц бодит хэрэглүүрийг боловсруулж эхэлсэн.

Би үүнийг MovieSwiftUI гэж нэрлэсэн - энэ нь шинэ болон хуучин кинонуудыг хайж олох, мөн тэдгээрийг ашиглан цуглуулгад цуглуулах програм юм. TMDB API. Би үргэлж кинонд дуртай байсан, тэр ч байтугай энэ чиглэлээр ажилладаг компанийг үүсгэн байгуулсан. Компанийг дажгүй гэж нэрлэх аргагүй байсан ч програм нь тийм байсан!

Бид танд сануулж байна: "Хабр" -ын бүх уншигчдад - "Habr" сурталчилгааны кодыг ашиглан Skillbox-ын аль ч курст бүртгүүлэхдээ 10 рублийн хөнгөлөлт.

Skillbox зөвлөж байна: Боловсролын онлайн курс "Мэргэжил Java хөгжүүлэгч".

Тэгэхээр MovieSwiftUI юу хийж чадах вэ?

  • API-тай харьцдаг - бараг ямар ч орчин үеийн програм үүнийг хийдэг.
  • Хүсэлт дээр асинхрон өгөгдлийг ачаалж, JSON-г ашиглан Swift загварт задлан шинжилдэг Кодлох боломжтой.
  • Хүсэлтийн дагуу ачаалагдсан зургуудыг харуулж, кэшлэнэ.
  • iOS, iPadOS болон macOS-д зориулсан энэхүү програм нь эдгээр үйлдлийн системүүдийн хэрэглэгчдэд хамгийн сайн UX-г өгдөг.
  • Хэрэглэгч өгөгдөл үүсгэж, өөрийн киноны жагсаалтыг үүсгэж болно. Програм нь хэрэглэгчийн өгөгдлийг хадгалж, сэргээдэг.
  • Харагдах байдал, бүрэлдэхүүн хэсэг, загваруудыг Redux загвар ашиглан тодорхой тусгаарласан. Энд өгөгдлийн урсгал нэг чиглэлтэй байна. Үүнийг бүрэн кэш болгож, сэргээж, дарж бичих боломжтой.
  • Уг програм нь SwiftUI, TabbedView, SegmentedControl, NavigationView, Form, Modal гэх мэт үндсэн бүрэлдэхүүн хэсгүүдийг ашигладаг. Энэ нь мөн захиалгат харагдац, дохио зангаа, UI/UX зэргийг өгдөг.

SwiftUI дээр програм хөгжүүлэлт. 1-р хэсэг: Dataflow ба Redux
Үнэн хэрэгтээ хөдөлгөөнт дүрс нь гөлгөр, GIF нь бага зэрэг шуугиантай болсон

Апп дээр ажиллах нь надад маш их туршлага өгсөн бөгөөд ерөнхийдөө эерэг туршлага болсон. Би бүрэн ажиллагаатай програм бичиж чадсан, 13-р сард би үүнийг сайжруулж, iOS XNUMX хувилбартай зэрэгцэн AppStore дээр нийтлэх болно.

Redux, BindableObject болон EnvironmentObject

SwiftUI дээр програм хөгжүүлэлт. 1-р хэсэг: Dataflow ба Redux

Би Redux-тай хоёр жил орчим ажиллаж байгаа болохоор харьцангуй сайн мэддэг. Ялангуяа би үүнийг for frontend-д ашигладаг урвалд вэб сайт, түүнчлэн уугуул iOS (Swift) болон Android (Kotlin) програмуудыг хөгжүүлэхэд зориулагдсан.

SwiftUI програм бүтээхэд өгөгдлийн урсгалын архитектур болгон Redux-ийг сонгосондоо би хэзээ ч харамсдаггүй. Redux-ийг UIKit программ дээр ашиглахад хамгийн хэцүү хэсэг бол дэлгүүртэй ажиллах, өгөгдөл авах, сэргээх, өөрийн үзэл бодол/бүрэлдэхүүнтэй зураглах явдал юм. Үүнийг хийхийн тулд би нэг төрлийн холбогч номын сан үүсгэх шаардлагатай болсон (ReSwift болон ReKotlin ашиглан). Сайн ажилладаг, гэхдээ маш их кодтой. Харамсалтай нь энэ нь (хараахан) нээлттэй эх сурвалж биш юм.

Сайн мэдээ! Хэрэв та Redux ашиглахаар төлөвлөж байгаа бол SwiftUI-д санаа зовох цорын ганц зүйл бол дэлгүүр, муж, бууруулагч юм. @EnvironmentObject-ийн ачаар дэлгүүртэй харилцах харилцааг SwiftUI бүрэн хариуцдаг. Тиймээс дэлгүүр нь BindableObject-ээр эхэлдэг.

Би энгийн Swift багц үүсгэсэн. SwiftUIFlux, энэ нь Redux-ийн үндсэн хэрэглээг хангадаг. Миний хувьд энэ нь MovieSwiftUI-ийн нэг хэсэг юм. Би ч бас алхам алхмаар зааварчилгаа бичсэн, энэ нь танд энэ бүрэлдэхүүн хэсгийг ашиглахад тусална.

энэ нь хэрхэн ажилладаг вэ?

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

Та ямар нэгэн үйлдэл хийх бүрдээ хурдны хайрцгийг идэвхжүүлдэг. Энэ нь програмын одоогийн төлөвийн дагуу үйлдлүүдийг үнэлэх болно. Энэ нь үйлдлийн төрөл болон өгөгдлийн дагуу шинэ өөрчлөгдсөн төлөвийг буцаана.

За, дэлгүүр нь BindableObject тул PassthroughSubject-с өгсөн willChange шинж чанарыг ашиглан үнэ нь өөрчлөгдөхөд SwiftUI-д мэдэгдэх болно. Учир нь BindableObject нь PublisherType-г өгөх ёстой, гэхдээ протоколын хэрэгжилт нь үүнийг удирдах үүрэгтэй. Ерөнхийдөө энэ бол Apple-ийн маш хүчирхэг хэрэгсэл юм. Үүний дагуу дараагийн үзүүлэх циклд SwiftUI нь төлөвийн өөрчлөлтийн дагуу үзэл бодлын үндсэн хэсгийг гаргахад туслах болно.

Үнэндээ энэ бол SwiftUI-ийн зүрх сэтгэл, ид шид юм. Одоо мужид бүртгүүлсэн ямар ч харагдац нь мужаас ямар өгөгдөл хүлээн авсан, юу өөрчлөгдсөнийг харгалзан үзэх болно.

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

Аппликейшн ажиллаж эхлэх үед дэлгүүрт EnvironmentObject хэлбэрээр нэвтэрч, @EnvironmentObject ашиглан дурын харагдацад хандах боломжтой. Үүсмэл шинж чанаруудыг програмын төлөвөөс хурдан олж авах эсвэл тооцоолдог тул гүйцэтгэлийн торгууль байхгүй.

Дээрх код нь киноны постер өөрчлөгдсөн тохиолдолд зургийг өөрчилнө.

Энэ нь үнэндээ зөвхөн нэг шугамаар хийгддэг бөгөөд үүний тусламжтайгаар үзэл бодол нь төртэй холбоотой байдаг. Хэрэв та iOS эсвэл бүр ReSwift дээр ажиллаж байсан бол холбох React-ийн тусламжтайгаар та SwiftUI-ийн ид шидийг ойлгох болно.

Одоо та үйлдлийг идэвхжүүлж, шинэ төлөвийг нийтлэхийг оролдож болно. Илүү төвөгтэй жишээ энд байна.

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

Дээрх кодонд би IP бүрт SwiftUI-ийн .onDelete үйлдлийг ашиглаж байна. Энэ нь жагсаалтын мөрийг устгахын тулд энгийн iOS шударалтыг харуулах боломжийг олгоно. Тиймээс хэрэглэгч устгах товчийг дарахад энэ нь холбогдох үйлдлийг өдөөж, киног жагсаалтаас хасдаг.

Жагсаалтын шинж чанар нь BindableObject төлөвөөс үүсэлтэй бөгөөд EnvironmentObject хэлбэрээр тарьдаг тул ForEach нь киноны тооцоолсон шинж чанартай холбоотой тул SwiftUI жагсаалтыг шинэчилдэг.

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
}

Дээр дурдсанчлан үйлдлийг илгээж, шинэ төлөвийг буцаах үед бууруулагчийг гүйцэтгэнэ.

Би одоохондоо дэлгэрэнгүй ярихгүй - SwiftUI юу харуулахаа хэрхэн мэддэг. Үүнийг илүү гүнзгий ойлгохын тулд энэ нь үнэ цэнэтэй юм өгөгдлийн урсгал дээр WWDC сессийг харах SwiftUI дээр. Мөн яагаад, хэзээ хэрэглэх талаар дэлгэрэнгүй тайлбарласан Төрийн, @Binding, ObjectBinding болон EnvironmentObject.

Skillbox зөвлөж байна:

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх