Search code examples
iosswiftreduxreswift

How organize action-state flow of upload/download methods using ReSwift


I'm building application using Redux architecture with ReSwift framework, most of applications processes described by action - reducer - state flow. Now I have added two methods upload(image: UIImage, fileName: String) and download(fileName: String), which uploading and downloading images to Firebase storage. So, how I can describe theses methods using Redux flow? Well, I know how I can run downloading/uploading processes using middleware, but how I can get results of download/upload in store subscribers?


Solution

  • You can create actions that will either hold the results or an error like this:

    struct ImageDownloadStartAction: Action {
        let filename: String
    }
    
    struct ImageDownloadSuccessAction: Action {
        let data: Data
    }
    
    struct ImageDownloadFailureAction: Action {
        let error: Error
    }
    
    
    struct ImageUploadStartAction: Action {
        let image: UIImage
        let filename: String
    }
    
    struct ImageUploadSuccessAction: Action { }
    
    struct ImageUploadFailureAction: Action {
        let error: Error
    }
    

    Then in your completionHandler or done block, you can use the dispatch function passed to the middleware to dispatch the success/failure action on the main thread (for example, DispatchQueue.main.async) and use the value or error in your reducer.

    For example (using PromiseKit):

    let networkMiddleware: Middleware<AppState> = { dispatch, getState in
        return { next in
            return { action in
                next(action)
    
                switch action {
                case let action as ImageDownloadStartAction:
                    networkService.download(filename: action.filename)
                    .done { // automatically called on main thread in PromiseKit
                        dispatch(ImageDownloadSuccessAction(data: $0)
                    }
                    .catch { // automatically called on main thread in PromiseKit
                        dispatch(ImageDownloadFailureAction(error: $0)
                    }
    
                default:
                    break
                }
            }
        }