Swift And Pizza
Swift And Pizza

September 2023
M T W T F S S
 123
45678910
11121314151617
18192021222324
252627282930  

Categories


Flux with SwiftUI and Combine

An easy conversion of a Flux Swift project using SwiftUI and Combine

Daniele BogoDaniele Bogo

In my previous post I wrote about the Flux pattern in Swift, making a simple project to explain how easy and powerful is this pattern using the WordPressFlux library.
Also since Apple introduced SwiftUI and Combine at the WWDC 2019, a lot of examples and posts appeared showing Flux as possible FRP solution.

In fact being familiar with the WordPressFlux library used in the WordPress iOS app resulted to be a big step forward in my approach with SwiftUI. Furthermore its consistency allowed me to avoid any huge refactor when I converted a project to SwiftUI.

Let me show you why!

2 structures, same flow

This is the diagram of the Info section of the application I made as test and as you can see the only main difference (except the presentation layer) is on the view model.

import Foundation
import WordPressFlux
import Combine

class InfoViewModel<Service: RemoteService>: ObservableObject {
    @Published private (set) var state: FetchingStatus = .idle

    var sections: [InfoSection] {
        return store.getSections()
    }

    private var storeReceipt: Receipt?
    private let store: InfoStore<Service>

    init(store: InfoStore<Service>) {
        self.store = store
        storeReceipt = store.onStateChange { [weak self] (_, state) in
            self?.state = state.status
        }
    }
    
    func fetchInfo() {
        store.onDispatch(InfoStoreAction.fetch)
    }
}

First thing, the Observable protocol is replaced by ObservableObject, which is introduced by the Combine module. This means our view model will be implemented as ObservedObject.

@ObservedObject private var viewModel: InfoViewModel<PizzeriaService>

The Dispatcher is removed and the state property doesn’t need to emit the change in its didSet because of the property wrapper @Published.

When the view model will be implemented in our view it will be declared as @ObservedObject

@ObservedObject private var viewModel: InfoViewModel<PizzeriaService>

and instead of updating the view in viewModel.onChange the view will be updated when self.viewModel.state will change

var body: some View {
        NavigationView {
            viewForState(self.viewModel.state)
                .navigationBarTitle(Text(Constants.ScreenTitles.info), displayMode: .inline)
                .navigationViewStyle(StackNavigationViewStyle())
        }
        .onAppear {
            self.viewModel.fetchInfo()
        }
    }

And that’s it!

You can find the new SwiftUI + Combine + Flux project here

Mobile Wrangler aka iOS Software Engineer | Pizza lover

Comments 0
There are currently no comments.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: