Using SwiftCurrent with MVVM Part 2
Pt 2. The second. Say it’s not so, Expenso!
In part 1, I forked Wiggles to update it to use SwiftCurrent. Ultimately, that proved trivial to do and didn’t really impact much, so this time I’m going to fork Expenso and see if that proves any harder to do.
Moderately Expenso
Getting Started
Unlike last time, Expenso already has some dependencies, and they are being brought in with CocoaPods. Like last time, this is a SwiftUI app, so I’ll limit my pod install to just bring in SwiftUI needed things.
Finding the First Workflow
Like last time, I’ll track down the screens I want to use to create a Workflow. Starting with ExpensoApp, I see that there is a conditional view.
Digging through AuthenticateView, we see that it also leads to ExpenseView. LIGHTBULB! These 2 screens definitely need to be in the same workflow. Let’s go ahead and convert these to use SwiftCurrent. First, we conform them to the protocol.
Let’s make sure everything is still working.
Good, everything works.
Making the First Workflow
Let’s switch to SwiftCurrent for the starting view. Something we’re going to want to change is that the view showing AuthenticateView shouldn’t be the one to have to check for if we use authentication. AuthenticateView should be responsible for that. So let’s implement shouldLoad, but because this is MVVM, the view is going to request the model to do that logic:
Now, I just need to remove the NavigationLink from AuthenticateView and have it proceedInWorkflow when it successfully authenticates.
Not shown in this screenshot is the change to have didAuthenticate to be Published. Something else I’m noticing is that we have a NavigationView defined in each view, and these are causing an issue with the action sheets. So I will remove the navigation views and leave only 1 call to hide the navigation bar per view. Once I’ve done that, then I’ll make the Workflow in ExpensoApp.
And let’s see if it works.
Woohoo! We got AuthenticateView into the workflow, and it optionally shows up based on the logic found in its view model.
Finish the Workflow
I think our workflow should take us all the way to the details for an expense, so let’s update ExpenseDetailedView. Like last time, I edited the init and conformed to FlowRepresentable, and I removed the NavigationView (though this was not strictly necessary).
Now over in ExpenseView, there’s a little wrinkle. The navigation link to the details is inside ExpenseMainView, but that view is not what we want to be FlowRepresentable. So we’re going to update ExpenseMainView to take a binding called selectedExpense.
And ExpenseView will now have a State for the selectedExpense that will be monitored, and when it changes, we’ll move forward.
Now update the Workflow in ExpensoApp:
WHEW! We’re finally done!
What’s next?
This time around, we did have to adjust a little bit about our views and our models, but overall this was still pretty straightforward. We could keep going and see what would happen if every screen was FlowRepresentable, but I think that would pan out the same as we’ve been seeing. Did we gain anything integrating SwiftCurrent here? Well, ExpenseView no longer references ExpenseDetailedView, nor does AuthenticateView have a reference to ExpenseView. AuthenticateView is now responsible for when it should appear, which means with a little more modification, we could update it to be a PassthroughFlowRepresentable and drop it at various points in the application (maybe requiring another authentication when updating settings or editing an expense).
Again, shout out to Sameer Nawaz for open sourcing these great-looking apps! And drop a comment if there’s anything more you’d like to dig into, or try out SwiftCurrent in your own app, and let me know how it goes!