SwiftUI இல் பயன்பாட்டு மேம்பாடு. பகுதி 1: Dataflow மற்றும் Redux

SwiftUI இல் பயன்பாட்டு மேம்பாடு. பகுதி 1: Dataflow மற்றும் Redux

WWDC 2019 இல் ஸ்டேட் ஆஃப் தி யூனியன் அமர்வில் கலந்து கொண்ட பிறகு, SwiftUI இல் ஆழ்ந்து செல்ல முடிவு செய்தேன். நான் அதனுடன் வேலை செய்வதில் நிறைய நேரம் செலவழித்தேன், இப்போது ஒரு உண்மையான பயன்பாட்டை உருவாக்கத் தொடங்கினேன், அது பரந்த அளவிலான பயனர்களுக்கு பயனுள்ளதாக இருக்கும்.

நான் அதை MovieSwiftUI என்று அழைத்தேன் - இது புதிய மற்றும் பழைய படங்களைத் தேடுவதற்கும், அவற்றைப் பயன்படுத்தி சேகரிப்பில் சேகரிப்பதற்குமான ஒரு பயன்பாடாகும். TMDB API. நான் எப்பொழுதும் திரைப்படங்களை நேசித்தேன் மற்றும் இந்த துறையில் பணிபுரியும் ஒரு நிறுவனத்தை கூட நீண்ட காலத்திற்கு முன்பு உருவாக்கினேன். நிறுவனம் குளிர் என்று அழைக்க முடியாது, ஆனால் பயன்பாடு இருந்தது!

நாங்கள் நினைவூட்டுகிறோம்: "Habr" இன் அனைத்து வாசகர்களுக்கும் - "Habr" விளம்பரக் குறியீட்டைப் பயன்படுத்தி எந்த Skillbox படிப்பிலும் சேரும்போது 10 ரூபிள் தள்ளுபடி.

Skillbox பரிந்துரைக்கிறது: கல்வி ஆன்லைன் படிப்பு "தொழில் ஜாவா டெவலப்பர்".

எனவே MovieSwiftUI என்ன செய்ய முடியும்?

  • API உடன் தொடர்பு கொள்கிறது - கிட்டத்தட்ட எந்த நவீன பயன்பாடும் இதைச் செய்கிறது.
  • கோரிக்கைகளில் ஒத்திசைவற்ற தரவை ஏற்றுகிறது மற்றும் JSON ஐ ஸ்விஃப்ட் மாதிரியில் பாகுபடுத்துகிறது குறியிடக்கூடியது.
  • கோரிக்கையின் பேரில் ஏற்றப்பட்ட படங்களைக் காட்டுகிறது மற்றும் அவற்றை தேக்ககப்படுத்துகிறது.
  • iOS, iPadOS மற்றும் macOS க்கான இந்தப் பயன்பாடு, இந்த OSகளின் பயனர்களுக்கு சிறந்த UXஐ வழங்குகிறது.
  • பயனர் தரவை உருவாக்கலாம் மற்றும் அவர்களின் சொந்த திரைப்படப் பட்டியலை உருவாக்கலாம். பயன்பாடு பயனர் தரவைச் சேமித்து மீட்டமைக்கிறது.
  • காட்சிகள், கூறுகள் மற்றும் மாதிரிகள் Redux வடிவத்தைப் பயன்படுத்தி தெளிவாகப் பிரிக்கப்படுகின்றன. இங்கே தரவு ஓட்டம் ஒரே திசையில் உள்ளது. இது முழுவதுமாக தற்காலிக சேமிப்பு, மீட்டமை மற்றும் மேலெழுதப்படலாம்.
  • பயன்பாடு SwiftUI, TabbedView, SegmentedControl, NavigationView, Form, Modal போன்றவற்றின் அடிப்படைக் கூறுகளைப் பயன்படுத்துகிறது. இது தனிப்பயன் காட்சிகள், சைகைகள், UI/UX ஆகியவற்றையும் வழங்குகிறது.

SwiftUI இல் பயன்பாட்டு மேம்பாடு. பகுதி 1: Dataflow மற்றும் Redux
உண்மையில், அனிமேஷன் மென்மையானது, GIF ஒரு சிறிய முட்டாள்தனமாக மாறியது

பயன்பாட்டில் பணிபுரிவது எனக்கு நிறைய அனுபவத்தை அளித்தது மற்றும் ஒட்டுமொத்தமாக இது ஒரு நேர்மறையான அனுபவமாக இருந்தது. நான் ஒரு முழுமையான செயல்பாட்டு பயன்பாட்டை எழுத முடிந்தது, செப்டம்பரில் நான் அதை மேம்படுத்தி, iOS 13 இன் வெளியீட்டில் ஒரே நேரத்தில் AppStore இல் வெளியிடுவேன்.

Redux, BindableObject மற்றும் EnvironmentObject

SwiftUI இல் பயன்பாட்டு மேம்பாடு. பகுதி 1: Dataflow மற்றும் Redux

நான் இப்போது இரண்டு வருடங்களாக Redux உடன் பணிபுரிந்து வருகிறேன், அதனால் நான் அதை நன்கு அறிந்திருக்கிறேன். குறிப்பாக, நான் அதை முன்பக்கத்தில் பயன்படுத்துகிறேன் வினை இணையதளம், அத்துடன் சொந்த iOS (Swift) மற்றும் Android (Kotlin) பயன்பாடுகளை உருவாக்குவதற்கும்.

ஸ்விஃப்ட்யூஐ அப்ளிகேஷனை உருவாக்குவதற்கான டேட்டா ஃப்ளோ ஆர்க்கிடெக்சராக Reduxஐத் தேர்ந்தெடுத்ததற்கு நான் ஒருபோதும் வருத்தப்படவில்லை. UIKit பயன்பாட்டில் Redux ஐப் பயன்படுத்தும் போது மிகவும் சவாலான பகுதிகள் ஸ்டோருடன் பணிபுரிவது மற்றும் தரவைப் பெறுவது மற்றும் மீட்டெடுப்பது மற்றும் உங்கள் பார்வைகள்/கூறுகளுக்கு மேப்பிங் செய்வது. இதைச் செய்ய, நான் ஒரு வகையான இணைப்பிகளின் நூலகத்தை உருவாக்க வேண்டியிருந்தது (ReSwift மற்றும் ReKotlin ஐப் பயன்படுத்தி). நன்றாக வேலை செய்கிறது, ஆனால் நிறைய குறியீடு. துரதிர்ஷ்டவசமாக, இது (இன்னும்) திறந்த மூலமாக இல்லை.

நல்ல செய்தி! SwiftUI பற்றி கவலைப்பட வேண்டிய ஒரே விஷயங்கள் - நீங்கள் Redux ஐப் பயன்படுத்த திட்டமிட்டால் - கடைகள், மாநிலங்கள் மற்றும் குறைப்பவர்கள். @EnvironmentObject க்கு நன்றி ஸ்விஃப்ட்யூஐ மூலம் கடையுடனான தொடர்பு முழுமையாகக் கவனிக்கப்படுகிறது. எனவே, ஸ்டோர் ஒரு BindableObject உடன் தொடங்குகிறது.

நான் ஒரு எளிய ஸ்விஃப்ட் தொகுப்பை உருவாக்கினேன், 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)
    }
}

ஒவ்வொரு முறையும் நீங்கள் ஒரு செயலைத் தூண்டும்போது, ​​கியர்பாக்ஸைச் செயல்படுத்துகிறீர்கள். இது பயன்பாட்டின் தற்போதைய நிலைக்கு ஏற்ப செயல்களை மதிப்பிடும். செயல் வகை மற்றும் தரவுக்கு ஏற்ப இது ஒரு புதிய மாற்றியமைக்கப்பட்ட நிலையை வழங்கும்.

சரி, ஸ்டோர் ஒரு பைண்டபிள் ஆப்ஜெக்ட் என்பதால், PassthroughSubject வழங்கிய willChange பண்பைப் பயன்படுத்தி அதன் மதிப்பு மாறும்போது SwiftUIஐ அது தெரிவிக்கும். ஏனென்றால், BindableObject ஒரு வெளியீட்டாளர் வகையை வழங்க வேண்டும், ஆனால் அதை நிர்வகிப்பதற்கு நெறிமுறை செயலாக்கம் பொறுப்பாகும். ஒட்டுமொத்தமாக, இது ஆப்பிளின் மிகவும் சக்திவாய்ந்த கருவியாகும். அதன்படி, அடுத்த ரெண்டரிங் சுழற்சியில், ஸ்விஃப்ட்யூஐ நிலை மாற்றத்திற்கு ஏற்ப காட்சிகளை வழங்க உதவும்.

உண்மையில், இது 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 ஐப் பயன்படுத்தி எந்தப் பார்வையிலும் அணுக முடியும். செயல்திறன் அபராதம் இல்லை, ஏனெனில் பெறப்பட்ட பண்புகள் விரைவாக மீட்டெடுக்கப்படுகின்றன அல்லது பயன்பாட்டு நிலையிலிருந்து கணக்கிடப்படுகின்றன.

திரைப்பட போஸ்டர் மாறினால் மேலே உள்ள குறியீடு படத்தை மாற்றிவிடும்.

இது உண்மையில் ஒரு வரியுடன் செய்யப்படுகிறது, இதன் உதவியுடன் காட்சிகள் மாநிலத்துடன் இணைக்கப்பட்டுள்ளன. நீங்கள் iOS இல் ReSwift உடன் பணிபுரிந்திருந்தால் அல்லது கூட இணைக்க ரியாக்ட் மூலம், 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!]))
            }
        }
    }
}

மேலே உள்ள குறியீட்டில், ஒவ்வொரு ஐபிக்கும் SwiftUI இலிருந்து .onDelete செயலைப் பயன்படுத்துகிறேன். இது பட்டியலில் உள்ள வரிசையை நீக்குவதற்கான சாதாரண iOS ஸ்வைப் காட்ட அனுமதிக்கிறது. எனவே பயனர் நீக்கு பொத்தானைத் தொடும்போது, ​​அது தொடர்புடைய செயலைத் தூண்டுகிறது மற்றும் பட்டியலிலிருந்து திரைப்படத்தை நீக்குகிறது.

சரி, பட்டியல் சொத்து BindableObject நிலையிலிருந்து பெறப்பட்டு சுற்றுச்சூழல் பொருளாக உட்செலுத்தப்பட்டதால், SwiftUI பட்டியலை புதுப்பிக்கிறது, ஏனெனில் ForEach திரைப்படங்கள் கணக்கிடப்பட்ட சொத்துடன் தொடர்புடையது.

மூவிஸ்ஸ்டேட் குறைப்பான் பகுதி இதோ:

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

கருத்தைச் சேர்