Hello again! Today I’m going to be writing again about FlexDataSource, this time integrating another library in LithoByte’s arsenal of tools, fuikit
(functional UIKit). If you’d like more background on that library, I’ll refer you to another blog post here. I’d summarize fuikit
as a way to tap into the functions of boilerplate UIKit classes outside of scope. Especially in the case of UIViewController
s, this is useful for a variety of reasons, one being that you can abstract styling and configuring your tableView
s and collectionViews
to outside of the UIViewController
. The ideal that I strive for as a developer is to just have my ViewControllers as a container for local variables, outlets, and actions, where all computation and logic that happens therein occurs outside of the actual ViewController. Let’s take a look at a simplified version of FPUIViewController
:

Here, we override the viewDidLoad
method in the View Controller, call its superclass’ viewDidLoad
, and then call an optional function called onViewDidLoad
on itself. The things I mentioned above can all happen outside of this FUIViewController
, and what we did in the last blog post will become a lot cleaner doing so. Similar to last time, we still use our FlexModelItem
to store our configuring function, and have a function that returns our network call.

Now, let’s define our new UsersViewController
which will now inherit from the FUIViewController
we defined above.

That’s it. That’s our View Controller. Four lines, doable in two with weird formatting. Now, let’s define a function that’ll take in a function called styleVC
, that will take in a UsersViewController
and return Void
, and return the UsersViewController
we create.

The static function makeFromXIB
is from a library called PlaygroundVCHelpers, which provides useful helper functions to instantiate your View Controllers. Now let’s make a function called dataSource
that will take in a network call and return a publisher of a FlexDataSource
.

Just like last time, we use the modelItem
function to create another function that will map User
s to FlexDataSourceItem
s, and then map the resulting array of items to a FlexDataSourceSection
the section into an array of that section, then that section array to a FlexDataSource
.
Finally, let’s make a configureVC
function that takes a UsersViewController
and a CombineNetCall
, uses our dataSource
function to generate the publisher, sinks into said publisher, and finally sets it to our UITableView
‘s dataSource
property.

Note that setting the tableView
property of our FlexDataSource
will in turn set the dataSource
property of that tableView
.
Now we have all the tools in place to create what we had at the end of my last post, but now our UsersViewController
is only four lines of code. We just need to fill in our usersViewController
function:

That’s it! I think it’s important to note that complex code is complex, and sometimes it’s inevitable that your UIViewController
will be hundreds of lines of code. Being an iOS consultant/developer, you spend a lot of time thinking about the intersection between what’s repeatable in Swift and what can be automated. You’ll find that abstracting out this intersection will result in less lines of code 90% of the time, but will scale better 100% of the time. Now when you want to add a new feature in your UserTableViewCell
, you know exactly how to do it (add the outlet in your class, then add to your configureCell
function). When you want to add a new feature in your UsersViewController
, you just tap into its onViewDidLoad
. You know this function will have access to all of your VC’s outlets, because you know exactly when it is called. There have been many times where I try to initialize a UIViewController
and access its outlets, only for my app to crash because the view hadn’t loaded yet. You can keep your auxiliary functions in different files or folders, and you can achieve better test coverage using more free-functions vs. executing your logic in your ViewControllers. FlexDataSource, FunNet, and fuikit are the three pods that I use most, and they are just as useful by themselves as they are with each other.