The Clean Swift Handbook is an updated version of this blog post, plus additional chapters to cover the entire CleanStore sample app. It also works with the latest versions of the Clean Swift templates, Xcode, and Swift. Check out the handbook for even more bonus materials.
Your client asks for an estimate to fix a bug. You tell him maybe a couple hours. But you know deep down in your gut that you just aren’t sure. You just have to give a number.
If it takes longer than your guesstimate, it comes back to bite you. “I thought you said it would be done in a couple hours.”
Promise broken. Trust lost. Resentment developed. Client fired. Money lost.
To make matters worse, as developers, we have a tendency to underestimate how long something will take.
Maybe the problem lies in the client? They just don’t understand how development works.
- They don’t know how complicated that thing is.
- They need to stop changing requirements.
- They should focus on functions, not UI first.
- If only they had asked me to do that 2 months ago while the code was still fresh, it would have taken less time.
- Add your own favorite lines here
You have to understand the code. Navigate through 50 classes, protocols, and methods. Trace through various conditionals and loops. Identify the relevant line. Reproduce the bug. Make a change to see how it behaves differently. Rinse and repeat until you fix the bug.
While doing all of these, you fear you may break something else. Because there is no unit tests to prevent regression.
This same vicious cycle happens every time you need to fix a bug or add a new feature. Thanks to Massive View Controller.
Failed Attempt at Solving the MVC Problem
If this sounds familiar to you, you may have already attempted to fix the situation. You read a lot about design patterns and how to refactor your view controllers. Extract your data sources and delegates. Put your business logic in the models. How that is supposed to help you write unit tests.
But you are still not doing it. It is 2015. Swift hits 2.0 and iOS 9 is released next month.
So far, the things you read and tried are what I call the first aid kit. Damage has already been done. You are just putting bandages on your wounds. You are treating the symptoms, not attacking the root cause.
Can we prevent the damage in the first place, instead of treating the wounds afterward? Why does it have a “re” in refactoring? Can we just write factored code from the start so we never have to refactor?
The Root Cause
About 2 years ago, I decided to do something serious about it. I want to find out why we are still battling massive view controllers. Nonetheless, refactoring and testing are generating all the buzz these days. Is it really possible to write factored code and never have to refactor?
Enter architecture. If a building has a shaky foundation, it eventually topples. If your codebase has a shaky architecture, it’ll eat you alive. Until you have enough. Let’s just rewrite it. We all know how expensive a rewrite is.
I’ve researched on various iOS architectures out there such as MVC, MVVM, ReactiveCocoa, and VIPER. I’ve also experimented with different testing and mocking frameworks. I’ll write more about these topics in future posts. In order to help you today, I want to focus on how to apply Uncle Bob’s Clean Architecture to iOS development using Swift. I’ll just call this Clean Swift. After reading this post, you’ll learn how to:
- Find and fix bugs faster and easier.
- Change existing behaviors with confidence.
- Add new features easily.
- Write shorter methods with single responsibility.
- Decouple class dependencies with established boundaries.
- Extract business logic from view controllers into interactors.
- Build reusable components with workers and service objects.
- Write factored code from the start.
- Write fast and maintainable unit tests.
- Have confidence in your tests to catch regression.
- Apply what you learn to new and existing projects of any size.
What if you know exactly which file to open and which method to look? How much more productive can you be? Imagine your tests run in seconds instead of minutes or hours. And you don’t need to learn any testing or mocking frameworks. No CocoaPods to install.
You just follow a simple system and your code just logically falls into place. That’s how you know exactly where to look when you look back at your code 3 months later.
In order to make it even easier for you to get started, I created a set of Xcode templates. You can generate the Clean Swift components with just Xcode’s New File command. When you subscribe to my list below, you’ll receive the templates in your inbox and updates. I’ll also send you future posts on leveling up your architecture. We’ll examine the details of interactors, workers, and service objects, look at how routing works with multiple storyboards (yes, it works like a charm with multiple storyboards). Subscribe below and you’ll receive all these goodies.
Make sure to also read about the latest updates to the templates for Xcode 8.3.3 & 9.0 and Swift 3 & 4.
Introducing Clean Swift – Clean Architecture for iOS
The Clean Swift architecture is derived from the Clean Architecture proposed by Uncle Bob. They share many common concepts such as the components, boundaries, and models. I’m going to implement the same create order use case in one of Uncle Bob’s talks. While Uncle Bob demonstrates the Clean Architecture using Java in web applications, I’ll show you how to apply Clean Architecture using Swift in iOS projects.
Before we begin, make sure you subscribe to my list in the form above to get my Xcode templates. Why bother writing all the boilerplate code by hand when you can click a button to generate them?
If you aren’t ready for Swift yet, I also have an Objective-C version of my Xcode templates and am looking for people to test it with more project types. If this is you, please email me after you subscribe. I’ll send you the Objective-C version. Your feedback will help guide the design of the components as there are differences in the languages.
The “Create Order” Use Case
This use case was presented in Uncle Bob’s Why can’t anyone get Web architecture right? talk. It originates from Ivar Jacobson’s book Object Oriented Software Engineering: A Use Case Driven Approach. It is a very good example as it encompasses most of the features of Clean Swift except routing. I’ll write a post on all the details on routing later.
Data:
– Customer-id
– Customer-contact-info
– Shipment-destination
– Shipment-mechanism
– Payment-information
Primary Course:
1. Order clerk issues “Create Order” command with above data.
2. System validates all data.
3. System creates order and determines order-id.
4. System delivers order-id to clerk.
Exception Course: Validation Error
1. System delivers error message to clerk.
We’ll model the data in the use case in our model layer and create special request, response, and view models to pass around at the boundaries between the view controller, interactor, and presenter components. We’ll implement each of the primary course item and validation as business logic in the interactor and, if necessary, workers.
To avoid getting lost, let’s first look at how we organize our code in the Xcode project.
Organizing Your Code in Xcode
We’ll create a new Xcode project and name it CleanStore. Just choose Single View Application and iPhone only for simplicity’s sake. Make sure the language is set to Swift. Next, create a nested sub-group Scenes -> CreateOrder. When we implement a delete order use case in the future, we’ll create a new sub-group Scenes -> DeleteOrder.
In a typical Xcode project, it is common to see files organized into model, view, and controller groups. But every iOS developer knows MVC. It doesn’t tell you anything specific about the project. As Uncle Bob pointed out, group and file names should reveal your intentions for the use cases. It should not reflect the underlying framework structure. So we’ll organize each use case under a new group nested within Scenes.
Inside the CreateOrder group, you can expect all files have something to do with creating an order. Likewise, under the DeleteOrder group, you’ll find code that deals with deleting an order. If you see a new ViewOrderHistory group created by another developer, you already know what to expect.
This organization tells you far more than the model, view, and controller groups you are used to see. Over time, you’ll accumulate 15 models, 27 view controllers, and 17 views. What do they do? You simply don’t know before you inspect each file.
You may ask. What about the shared classes and protocols used by CreateOrder, DeleteOrder and ViewOrderHistory? Well, you can put them in a separate group called Common -> Order. How about that for simplicity?
Back to our use case.
Under the new CreateOrder group, we’ll create the following Clean Swift components. As we work through the use case, we’ll add methods to the component’s input and output protocols and then implement them in the components. Make sure you join my email list, so you can use my Xcode templates to create all these components automatically for you with a few clicks.
Watch this screencast now to see how to generate the seven Clean Swift components using the Xcode templates to save a lot of time!
You can now compile your project and start building your UI in storyboard. But let’s briefly examine the components you’ve just created first.
The VIP Cycle
The view controller, interactor, and presenter are the three main components of Clean Swift. They act as input and output to one another as shown in the following diagram.
The view controller’s output connects to the interactor’s input. The interactor’s output connects to the presenter’s input. The presenter’s output connects to the view controller’s input. We’ll create special objects to pass data through the boundaries between the components. This allows us to decouple the underlying data models from the components. These special objects consists of only primitive types such as Int, Double, and String. We can create structs, classes, or enums to represent the data but there should only be primitive types inside these containing entities.
This is important because when the business rules change that result in changes in the underlying data models. We don’t need to update all over the codebase. The components act as plugins in Clean Swift. That means we can swap in different components provided they conform to the input and output protocols. The app still works as intended.
A typical scenario goes like. The user taps a button in the app’s user interface. The tap gesture comes in through the IBActions in the view controller. The view controller constructs a request object and sends it to the interactor. The interactor takes the request object and performs some work. It then puts the results in a response object and sends it to the presenter. The presenter takes the response object and formats the results. It then puts the formatted result in a view model object and sends it back to the view controller. Finally, the view controller displays the results to the user.
1. View Controller
What should a view controller do in an iOS app? The base class name UITableViewController
should tell you something. You want to put code there to control UITableView
and UIView
subclasses. But what does this control code look like? What qualifies as control code and what doesn’t?
Let’s dive in.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
import UIKit protocol CreateOrderViewControllerInput { func displaySomething(viewModel: CreateOrderViewModel) } protocol CreateOrderViewControllerOutput { func doSomething(request: CreateOrderRequest) } class CreateOrderViewController: UITableViewController, CreateOrderViewControllerInput { var output: CreateOrderViewControllerOutput! var router: CreateOrderRouter! // MARK: Object lifecycle override func awakeFromNib() { super.awakeFromNib() CreateOrderConfigurator.sharedInstance.configure(self) } // MARK: View lifecycle override func viewDidLoad() { super.viewDidLoad() doSomethingOnLoad() } // MARK: Event handling func doSomethingOnLoad() { // NOTE: Ask the Interactor to do some work let request = CreateOrderRequest() output.doSomething(request) } // MARK: Display logic func displaySomething(viewModel: CreateOrderViewModel) { // NOTE: Display the result from the Presenter // nameTextField.text = viewModel.name } } |
CreateOrderViewControllerInput
and CreateOrderViewControllerOutput
protocols
The CreateOrderViewControllerInput
protocol specifies the inputs to the CreateOrderViewController
component (it conforms to the protocol). The CreateOrderViewControllerOutput
protocol specifies the outputs. You’ll see this same pattern in the interactor and presenter later.
There is one method doSomething()
in the output protocol. If another component wants to act as the output of CreateOrderViewController
, it needs to support doSomething()
in its input.
From the VIP cycle you saw earlier, we know this output is going to be the interactor. But notice in CreateOrderViewController.swift
, there is no mention of CreateOrderInteractor
. This means we can swap in another component to be the output of CreateOrderViewController
as long as it supports doSomething()
in its input protocol.
The argument to doSomething()
is a request object that is passed through the boundary from the view controller to the interactor. This request object is a CreateOrderRequest
struct. It consists of primitive types, not the whole order data that we identified earlier. This means we have decoupled the underlying order data model from the view controller and interactor. When we make changes to the order data model in the future (for example, add an internal order ID field), we don’t need to update anything in the Clean Swift components.
I’ll come back to the displaySomething()
method in the output protocol later when we finish the VIP cycle.
output
and router
variables
The output
variable is an object that conforms to the CreateOrderViewControllerOutput
protocol. Although we know it is going to be the interactor, but it doesn’t need to be.
The router
variable is a reference to CreateOrderRouter and is used to navigate to different scenes.
configure()
method
We’ll make a call to CreateOrderConfigurator.sharedInstance.configure(self)
in awakeFromNib()
to ask the configurator to set up the VIP chain. There is no configurator in Uncle Bob’s Clean Architecture or VIPER (which does all the setup in the app delegate). I don’t really want to litter my VIP code with this extraneous setup code, so I extracted it to the configurator. We’ll take a look at the configurator later.
Flow of control
In viewDidLoad()
, we have some business logic to run, so we call doSomethingOnLoad()
. In doSomethingOnLoad()
, we create a CreateOrderRequest()
object and invoke doSomething(request)
on the output (the interactor). That’s it. We ask the output to perform our business logic. The view controller doesn’t and shouldn’t care who and how it is done.
2. Interactor
The interactor contains your app’s business logic. The user taps and swipes in your UI in order to interact with your app. The view controller collects the user inputs from the UI and passes it to the interactor. It then retrieves some models and asks some workers to do the work.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
import UIKit protocol CreateOrderInteractorInput { func doSomething(request: CreateOrderRequest) } protocol CreateOrderInteractorOutput { func presentSomething(response: CreateOrderResponse) } class CreateOrderInteractor: CreateOrderInteractorInput { var output: CreateOrderInteractorOutput! var worker: CreateOrderWorker! // MARK: Business logic func doSomething(request: CreateOrderRequest) { // NOTE: Create some Worker to do the work worker = CreateOrderWorker() worker.doSomeWork() // NOTE: Pass the result to the Presenter let response = CreateOrderResponse() output.presentSomething(response) } } |
CreateOrderInteractorInput
and CreateOrderInteractorOutput
protocols
The CreateOrderInteractorInput
protocol specifies the inputs to the CreateOrderInteractor
component (it conforms to the protocol). The CreateOrderInteractorOutput
protocol specifies the outputs.
We see the same doSomething()
method here in the CreateOrderInteractorInput
protocol as in the CreateOrderViewControllerOutput
protocol. The output of CreateOrderViewController
is connected to the input of the CreateOrderInteractor
.
The output protocol has one method presentSomething()
. The output of CreateOrderInteractor
needs to support presentSomething()
in order to act as the output. Hint: The output is going to be the P in VIP.
Another thing to note here is the argument to doSomething()
is the request object of type CreateOrderRequest
. This is the same method signature in the CreateOrderViewControllerOutput
protocol. The interactor peeks inside this request object to retrieve any necessary data to do its job.
Similarly, the argument to presentSomething()
is the response object of type CreateOrderResponse.
output
and worker
variables
The output
variable is an object that conforms to the CreateOrderInteractorOutput
protocol. Although we know it is going to be the presenter, but it doesn’t need to be.
The worker
variable of type CreateOrderWorker
is a specialized object that will actually create the new order. Since creating the order likely involves persistence in Core Data and making network calls. It is simply too much work for the interactor to do alone. Keep in mind the interactor also has to validate the order form and this is likely going to be extracted into its own worker.
Flow of control
When the input to CreateOrderInteractor
(i.e. CreateOrderViewController
) invokes doSomething()
, it first creates the worker object and asks it to do some work by calling doSomeWork()
. It then constructs a response object and invokes presentSomething()
on the output.
Let’s take a quick look at the worker next.
3. Worker
A profile view may need to fetch the user from Core Data, download the profile photo, allows users to like and follow, …etc. You don’t want to swamp the interactor with doing all these tasks. Instead, you can break it down into many workers, each doing one thing. You can then reuse the same workers elsewhere.
The CreateOrderWorker
is very simple as it just provides an interface and implementation of the work it can do to the interactor.
1 2 3 4 5 6 7 8 9 10 11 12 |
import UIKit class CreateOrderWorker { // MARK: Business Logic func doSomeWork() { // NOTE: Do the work } } |
4. Presenter
After the interactor produces some results, it passes the response to the presenter. The presenter then marshal the response into view models suitable for display. It then passes the view models back to the view controller for display to the user.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
import UIKit protocol CreateOrderPresenterInput { func presentSomething(response: CreateOrderResponse) } protocol CreateOrderPresenterOutput: class { func displaySomething(viewModel: CreateOrderViewModel) } class CreateOrderPresenter: CreateOrderPresenterInput { weak var output: CreateOrderPresenterOutput! // MARK: Presentation logic func presentSomething(response: CreateOrderResponse) { // NOTE: Format the response from the Interactor and pass the result back to the View Controller let viewModel = CreateOrderViewModel() output.displaySomething(viewModel) } } |
CreateOrderPresenterInput
and CreateOrderPresenterOutput
protocols
The CreateOrderPresenterInput
protocol specifies the inputs to the CreateOrderPresenter
component (it conforms to the protocol). The CreateOrderPresenterOutput
protocol specifies the outputs.
By now, the presentSomething()
and displaySomething()
methods don’t need to be explained. The CreateOrderResponse
argument is passed through the interactor-presenter boundary whereas the CreateOrderViewModel
argument is passed through the presenter-view controller boundary as the VIP cycle completes.
output
variable
The output
variable is an object that conforms to the CreateOrderPresenterOutput
protocol. Although we know it is going to be the view controller, but it doesn’t need to be. A subtle difference here is we make output
a weak variable to avoid a reference cycle when this CreateOrder scene is no longer needed and the components are deallocated.
Flow of control
Since the output of CreateOrderInteractor
is connected to the input of CreateOrderPresenter
, the presentSomething()
method will be called after the interactor finishes doing its work. It simply constructs the view model object and invokes displaySomething()
on the output.
I promised you that we would come back to the displaySomething()
method in the view controller. This is the last step in the VIP cycle. It takes any data in the view model object and displays it to the user. For example, we may want to display the customer’s name in a text field: nameTextField.text = viewModel.name
.
Congratulations! You just learned the essence of Clean Swift. You should now be able to extract business and presentation logic from your user interface code. But don’t worry. I won’t leave you without an example. But let’s finish talking about the rest of the Clean Swift components first.
5. Router
When the user taps the next button to navigate to the next scene in the storyboard, a segue is trigged and a new view controller is presented. A router extracts this navigation logic out of the view controller. It is also the best place to pass any data to the next scene. As a result, the view controller is left with just the task of controlling views.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
import UIKit protocol CreateOrderRouterInput { func navigateToSomewhere() } class CreateOrderRouter { weak var viewController: CreateOrderViewController! // MARK: Navigation func navigateToSomewhere() { // NOTE: Teach the router how to navigate to another scene. Some examples follow: // 1. Trigger a storyboard segue // viewController.performSegueWithIdentifier("ShowSomewhereScene", sender: nil) // 2. Present another view controller programmatically // viewController.presentViewController(someWhereViewController, animated: true, completion: nil) // 3. Ask the navigation controller to push another view controller onto the stack // viewController.navigationController?.pushViewController(someWhereViewController, animated: true) // 4. Present a view controller from a different storyboard // let storyboard = UIStoryboard(name: "OtherThanMain", bundle: nil) // let someWhereViewController = storyboard.instantiateInitialViewController() as! SomeWhereViewController // viewController.navigationController?.pushViewController(someWhereViewController, animated: true) } // MARK: Communication func passDataToNextScene(segue: UIStoryboardSegue) { // NOTE: Teach the router which scenes it can communicate with if segue.identifier == "ShowSomewhereScene" { passDataToSomewhereScene(segue) } } func passDataToSomewhereScene(segue: UIStoryboardSegue) { // NOTE: Teach the router how to pass data to the next scene // let someWhereViewController = segue.destinationViewController as! SomeWhereViewController // someWhereViewController.output.name = viewController.output.name } } |
CreateOrderRouterInput
protocol
The CreateOrderRouterInput
protocol specifies its routes – the scenes it can navigates to – to the view controller. The method navigateToSomewhere()
tells the view controller that: If you use me as your router, I know how to navigate to a scene called somewhere.
As you can see in the comment inside the navigateToSomewhere()
method, the router is very flexible in the number of ways it can navigate to another scene. I’ll talk all about the router in another post.
viewController
variable
The viewController
variable is just a reference to the view controller that uses this router. It is a weak variable to avoid the reference cycle problem, and is set up by the configurator as you’ll soon see. The Apple way of transitioning between segues adds all the present* and push* methods to the UIViewController
class. So we need to have viewController
here so we can call those methods in the router.
passDataToNextScene()
and passDataToSomewhereScene()
The passDataToNextScene()
and passDataToSomewhereScene()
methods provide a way for you to pass data to the next scene. You put pretty much the same code there as you would normally do for prepareForSegue()
. passDataToNextScene()
tries to match the segue identifier to dispatch to the more specific passDataToSomewhereScene()
which does the actual data passing.
6. Configurator
The configurator’s job is to hook up all the Clean Swift components above. I made a point to extract all setup code into the configurator so that you can focus on writing your app code. It is unlikely that you ever need to look at the configurator at all. But I’ll uncover the magic for you.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
import UIKit // MARK: Connect View, Interactor, and Presenter extension CreateOrderViewController: CreateOrderPresenterOutput { override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { router.passDataToNextScene(segue) } } extension CreateOrderInteractor: CreateOrderViewControllerOutput { } extension CreateOrderPresenter: CreateOrderInteractorOutput { } class CreateOrderConfigurator { // MARK: Object lifecycle class var sharedInstance: CreateOrderConfigurator { struct Static { static var instance: CreateOrderConfigurator? static var token: dispatch_once_t = 0 } dispatch_once(&Static.token) { Static.instance = CreateOrderConfigurator() } return Static.instance! } // MARK: Configuration func configure(viewController: CreateOrderViewController) { let router = CreateOrderRouter() router.viewController = viewController let presenter = CreateOrderPresenter() presenter.output = viewController let interactor = CreateOrderInteractor() interactor.output = presenter viewController.output = interactor viewController.router = router } } |
The extensions
Remember I told you there is no mention of the interactor in the view controller. The output
variable is defined to be of type CreateOrderViewControllerOutput
. You are also free to swap in another object to replace the interactor as the view controller’s output. But somehow the view controller needs to be hooked up to the interactor, right? That’s exactly what the three extensions at the beginning do.
The CreateOrderViewController
extension adds the CreateOrderPresenterOutput
protocol conformance. This means the presenter’s output is connected to the view controller. Similarly, the CreateOrderInteractor
extension adds the CreateOrderViewControllerOutput
protocol conformance. The CreateOrderPresenter
extension adds the CreateOrderInteractorOutput
protocol conformance.
Singleton
There should be only one configurator for each scene, and the connection setup code should run once and only once. I create a sharedInstance
class variable and invoke CreateOrderConfigurator.sharedInstance.configure(self)
in the view controller’s awakeFromNib()
method. This is the very first opportunity I have to do stuff right after the view controller object has been loaded from the storyboard. Unless I override the UIViewController
base class, and enforce you derive from it. But I didn’t want to do that.
configure()
method
This is where the arrows are drawn in the VIP cycle. Note the arrows are uni-directional. This consistent flow of control makes things very clear. It is the reason why you know exactly which file and method to look for when you are fixing bugs.
Only the view controller is loaded from the storyboard. We need to actually create the interactor, presenter, and router instances manually. The configure()
method does this, and then assigns the corresponding references to the output
, router
, and viewController
variables.
The important thing to remember here is the VIP cycle:
The output of the view controller is connected to the input of the interactor. The output of the interactor is connected to the input of the presenter. The output of the presenter is connected to the input of the view controller. This means the flow of control is always unidirectional.
Remembering the VIP cycle will become very handy when you implement features and fix bugs. You’ll know exactly which file and method to look for.
It also simplifies your dependency graph. You don’t want objects to have references to one another whenever they please. It may seem convenient for the view controller to ask the presenter directly to format a string. But over time, you’ll end up with a mess in your dependency graph. Keep this in mind at all times to avoid any unnecessary coupling.
This will become very clear when we implement the create order use case.
7. Models
In order to completely decouple the Clean Swift components, we need to define data models to pass through the boundaries between them, instead of just using raw data models. There are 3 primary types of models:
- Request – The view controller constructs a request model and passes it to the interactor. A request model contains mostly user inputs, such as text entered in text fields and values chosen in pickers.
-
Response – After the interactor finishes doing work for a request, it encapsulates the results in a response model and then passes it to the presenter.
-
View Model – After the presenter receives the response from the interactor, it formats the results into primitive data types such as String and Int, and stuff them in the view model. It then passes the view model back to the view controller for display.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import UIKit struct CreateOrderRequest { } struct CreateOrderResponse { } struct CreateOrderViewModel { } |
In the code generated by the templates, we don’t actually have any data in these models. So they are just empty. But you’ll see actual data when we implement the create order use case. Let’s see what this data looks like next.
Tired of all these boilerplate code? Subscribe below to get my Xcode templates to generate all these for you automagically.
“Create Order” Data
Let’s break down the create order use case to come up with the data required to create a new order. We’ll then create a form using table view and text fields in the app to collect this data from the user.
- Customer ID
- Integer
- Customer Contact Info
- First name
- Last name
- Phone
- Shipment Destination
- Shipping address
- Street 1
- Street 2
- City
- State
- ZIP
- Shipping address
- Shipment Mechanism
- Shipping method
- Next day
- 3 to 5 days
- Ground
- Shipping method
- Payment Information
- Credit card number
- Expiration date
- CVV
- Billing address
- Street 1
- Street 2
- City
- State
- ZIP
That’s a gigantic form! In a more realistic app, we’ll likely have some of this data already after the user has logged in such as name, phone, email, shipping and billing address, and maybe credit card info. So this form will be dramatically slimmed down.
“Create Order” Business Logic
Now, let’s see what business logic we can come up with from the use case’s requirements. This can serve as pseudocode that we’ll later write acceptance tests for.
- Order clerk issues “Create Order” command with above data.
- Display a form to collect data from user.
- Form uses text fields to collect text data.
- Form uses a picker to collect Shipping method and Expiration data.
- Form uses a switch to auto-fill Billing address from Shipping address.
- Form uses a button to issue the “Create Order” command.
- System validates all data.
- Ensure all fields except Street 2 are not blank.
- If valid, display a “valid” message below the button.
- If invalid, display error messages next to the invalid fields.
- System creates order and determines order-id.
- Generate an unique order ID.
- Create and store a new order in Core Data.
- System delivers order-id to clerk.
- Display order ID on screen to user.
This is a good set of initial features to demonstrate how Clean Swift works and its benefits. In future posts, we’ll expand this feature set to show how you can adapt to changes easily. Some future requirements may be:
- Use Core Location to reverse geocode current lat/lng to address to pre-fill shipping address and billing address.
- Integrate Stripe API to collect credit card info.
- Validate fields as data is entered instead of after the button is tapped.
- Add country to shipping and billing addresses to expand business overseas.
- Format phone number, credit card number, and expiration date.
Now we are ready to implement the create order use case.
Design the Create Order Form in Storyboard and View Controller
Where should we begin?
You want to start by collecting user inputs such as text and taps in the view controller. The view controller then passes the inputs to the interactor to get some work done. Next, the interactor passes the output to the presenter for formatting. Finally, the presenter asks the view controller to display the results.
This is the flow of control and it is always in one direction. The VIP cycle is not named VIP because of a very important person. It is because there is an order to things. V then I then P.
Let’s start by creating the create order form. In the storyboard, embed the CreateOrderViewController
in a UINavigationController
. Add a title Create Order to give it some context.
Make the table view use static cells. Add a new section for each group of data and a new cell for each piece of data required in the create order form. For each cell, add a UILabel
and UITextField
.
Make the following IBOutlet connections:
- Connect all the text fields to the
textFields
IBOutlet collection. Also set their delegates to be ourCreateOrderViewController
. - Connect the text field for shipping method to the
shippingMethodTextField
IBOutlet. - Connect the text field for expiration date to the
expirationDateTextField
IBOutlet.
Drag a UIPickerView
and UIDatePicker
from the Object Library to the scene. Then make the following IBOutlet connections:
- Connect the
UIPickerView
to theshippingMethodPicker
IBOutlet. Also set the data source and delegate to be ourCreateOrderViewController
. - Connect the
UIDatePicker
to theexpirationDatePicker
IBOutlet. Also control-drag from theUIDatePicker
to theCreateOrderViewController
in the assistant editor to create an IBAction for the value change event and name itexpirationDatePickerValueChanged()
.
Your form should look like:
It won’t win any design award, but it satisfies our use case requirements. The beauty of Clean Swift is you can modify the view later without affecting other parts of the app. For example, we can add country to shipping and billing addresses to expand the client’s business overseas. Or we can hire a professional designer to style the form.
After setting up the IBOutlets and IBActions, your CreateOrderViewController
should also contain the following code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// MARK: Text fields @IBOutlet var textFields: [UITextField]! // MARK: Shipping method @IBOutlet weak var shippingMethodTextField: UITextField! @IBOutlet var shippingMethodPicker: UIPickerView! // MARK: Expiration date @IBOutlet weak var expirationDateTextField: UITextField! @IBOutlet var expirationDatePicker: UIDatePicker! @IBAction func expirationDatePickerValueChanged(sender: AnyObject) { } |
Now the user interface is all set. Let’s tackle user interaction next. When the user taps the next button in the keyboard, we want him to be able to enter text for the next text field. Make the CreateOrderViewController
conform to the UITextFieldDelegate
protocol. Then add the textFieldShouldReturn()
method.
1 2 3 4 5 6 7 8 9 10 11 12 |
func textFieldShouldReturn(textField: UITextField) -> Bool { textField.resignFirstResponder() if let index = textFields.indexOf(textField) { if index < textFields.count - 1 { let nextTextField = textFields[index + 1] nextTextField.becomeFirstResponder() } } return true } |
When the user taps the table view cell (not the text field directly), we still want the user to be able to edit the text field. After all, using UITextBorderStyleNone
makes it impossible to see the boundary of the text field. Plus, it just feels better and a common behavior to be able to tap a label and edit the field. To achieve this behavior, add the tableView:didSelectRowAtIndexPath()
method.
1 2 3 4 5 6 7 8 9 10 11 |
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { if let cell = tableView.cellForRowAtIndexPath(indexPath) { for textField in textFields { if textField.isDescendantOfView(cell) { textField.becomeFirstResponder() } } } } |
Implement Shipping Methods Business Logic in the Interactor
Getting the pickers for shipping method and expiration date to work is pretty straight forward. But more importantly, this is where we encounter our first business logic.
Let’s look at shipping method first.
The available shipping methods can change in the client’s business as it partners with different shippers over time. We don’t want to leave it in the view controller. So, we’ll extract this business logic to the interactor.
Start by adding the configurePickers()
method and invoke it in viewDidLoad()
. When the user taps the shippingMethodTextField
, the correct picker UI will be shown instead of the standard keyboard.
1 2 3 4 5 6 7 8 9 10 11 |
override func viewDidLoad() { super.viewDidLoad() configurePickers() } func configurePickers() { shippingMethodTextField.inputView = shippingMethodPicker } |
Next, make CreateOrderViewController
conform to the UIPickerViewDataSource
and UIPickerViewDelegate
protocols, and add the following methods.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int { return 1 } func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { return output.shippingMethods.count } func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { return output.shippingMethods[row] } func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { shippingMethodTextField.text = output.shippingMethods[row] } |
Since the shipping method business logic is moved to the interactor, we can invoke it using output.shippingMethods
in the view controller. We then also need to add the shippingMethods
variable to the CreateOrderViewControllerOutput
and CreateOrderInteractorInput
protocols. We need to add it to both protocols because the configurator has connected the CreateOrderViewController
output to the CreateOrderInteractor
input. For now, we’ll keep things simple by assuming it is an array of fixed literal strings. In the future, we can retrieve the available shipping methods dynamically in Core Data or over the network.
In CreateOrderViewController
:
1 2 3 4 5 |
protocol CreateOrderViewControllerOutput { var shippingMethods: [String] { get } } |
In CreateOrderInteractor
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
protocol CreateOrderInteractorInput { var shippingMethods: [String] { get } } class CreateOrderInteractor: CreateOrderInteractorInput { var output: CreateOrderInteractorOutput! var worker: CreateOrderWorker! var shippingMethods = [ "Standard Shipping", "Two-Day Shipping ", "One-Day Shipping " ] } |
Implement Expiration Date Business Logic in the Interactor
The expiration date can be formatted differently depending on the user’s language and location. We’ll move this presentation logic to the presenter.
Let’s take care of the expiration date picker in configurePickers()
first.
1 2 3 4 5 6 |
func configurePickers() { shippingMethodTextField.inputView = shippingMethodPicker expirationDateTextField.inputView = expirationDatePicker } |
Next, modify the expirationDatePickerValueChanged()
method to look like:
1 2 3 4 5 6 7 |
@IBAction func expirationDatePickerValueChanged(sender: AnyObject) { let date = expirationDatePicker.date let request = CreateOrder_FormatExpirationDate_Request(date: date) output.formatExpirationDate(request) } |
After the user chooses an expiration date in the picker, the expirationDatePickerValueChanged()
method is invoked. We retrieve the date from the picker, and stuffs it in this weird looking thing called CreateOrder_FormatExpirationDate_Request
. It is simply a Swift struct that we define in CreateOrderModels.swift
. It has one data member named date
of NSDate
type.
1 2 3 4 5 |
struct CreateOrder_FormatExpirationDate_Request { var date: NSDate } |
You may wonder why I use _ here. Objective-C and Swift naming convention suggests using upper camel case for token names such as class, struct, and enum. Before you scream at me for breaking convection. Let me explain why I used _.
CreateOrder
is the name of the scene. FormatExpirationDate
is the intention or business rule. Request
indicates the boundary between the view controller and interactor. That’s why you get CreateOrder_FormatExpirationDate_Request
.
Contrast CreateOrder_FormatExpirationDate_Request
with CreateOrderFormatExpirationDateRequest
. Which one tells you about the scene, intention, and boundary more clearly? So I chose clarity over dogma.
Now, back to the expirationDatePickerValueChanged()
method.
After we create the request object and initialize it with the date the user has picked, we simply ask the output to format the expiration date by calling output.formatExpirationDate(request)
.
Yes, you guessed it right. We do need to add this new method to the CreateOrderViewControllerOutput
and CreateOrderInteractorInput
protocols.
In CreateOrderViewController
:
1 2 3 4 5 6 |
protocol CreateOrderViewControllerOutput { var shippingMethods: [String] { get } func formatExpirationDate(request: CreateOrder_FormatExpirationDate_Request) } |
In CreateOrderInteractor
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
protocol CreateOrderInteractorInput { var shippingMethods: [String] { get } func formatExpirationDate(request: CreateOrder_FormatExpirationDate_Request) } class CreateOrderInteractor: CreateOrderInteractorInput { // MARK: Expiration date func formatExpirationDate(request: CreateOrder_FormatExpirationDate_Request) { let response = CreateOrder_FormatExpirationDate_Response(date: request.date) output.presentExpirationDate(response) } } |
Implement Expiration Date Presentation Logic in the Presenter
In the formatExpirationDate()
method, we create the CreateOrder_FormatExpirationDate_Response
response object as defined in CreateOrderModels.swift
.
1 2 3 4 5 |
struct CreateOrder_FormatExpirationDate_Response { var date: NSDate } |
We initialize the response object with the date we get from the request model. The interactor does not do anything with the date and just passes is straight through by invoking output.presentExpirationDate(response)
. There is currently no business logic associated with the expiration date. Later, when we add validation to make sure the expiration date doesn’t fall in the past, we’ll add that business rule here in the interactor.
Let’s continue by adding the presentExpirationDate()
method to the CreateOrderInteractorOutput
and CreateOrderPresenterInput
protocols.
In CreateOrderInteractor
:
1 2 3 4 5 |
protocol CreateOrderInteractorOutput { func presentExpirationDate(response: CreateOrder_FormatExpirationDate_Response) } |
In CreateOrderPresenter
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
protocol CreateOrderPresenterInput { func presentExpirationDate(response: CreateOrder_FormatExpirationDate_Response) } class CreateOrderPresenter: CreateOrderPresenterInput { weak var output: CreateOrderPresenterOutput! let dateFormatter: NSDateFormatter = { let dateFormatter = NSDateFormatter() dateFormatter.dateStyle = .ShortStyle dateFormatter.timeStyle = NSDateFormatterStyle.NoStyle return dateFormatter }() // MARK: Expiration date func presentExpirationDate(response: CreateOrder_FormatExpirationDate_Response) { let date = dateFormatter.stringFromDate(response.date) let viewModel = CreateOrder_FormatExpirationDate_ViewModel(date: date) output.displayExpirationDate(viewModel) } } |
In CreateOrderPresenter
, we define a NSDateFormatter
constant. The presentExpirationDate()
method simply asks this date formatter object to convert the expiration date from NSDate
to String
. It then stuffs this date string representation in the CreateOrder_FormatExpirationDate_ViewModel
struct as defined in CreateOrderModels.swift
.
Note that the date in the view model is a String
, not NSDate
. A presenter’s job is to marshal data into a format suitable for display to the user. Since our UI displays the date in a UITextField
, we convert a date into a string. In fact, most of the time, the data in your view models will be either strings or numbers since that’s what human read.
1 2 3 4 5 |
struct CreateOrder_FormatExpirationDate_ViewModel { var date: String } |
It finally asks the view controller to display it by calling output.displayExpirationDate(viewModel)
.
This also means we need to define the displayExpirationDate()
method in the CreateOrderPresenterOutput
and CreateOrderViewControllerInput
protocols.
In CreateOrderPresenter
:
1 2 3 4 5 |
protocol CreateOrderPresenterOutput: class { func displayExpirationDate(viewModel: CreateOrder_FormatExpirationDate_ViewModel) } |
In CreateOrderViewController
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
protocol CreateOrderViewControllerInput { func displayExpirationDate(viewModel: CreateOrder_FormatExpirationDate_ViewModel) } class CreateOrderViewController: UITableViewController, CreateOrderViewControllerInput, UITextFieldDelegate, UIPickerViewDataSource, UIPickerViewDelegate { // MARK: Expiration date func displayExpirationDate(viewModel: CreateOrder_FormatExpirationDate_ViewModel) { let date = viewModel.date expirationDateTextField.text = date } } |
In the displayExpirationDate()
method, we just need to grab the date string from the view model and assign it to the textField, as in expirationDateTextField.text = date
.
That’s it. This completes the VIP cycle.
You can find the complete code example at https://github.com/Clean-Swift/CleanStore.
You’ve got a working create order form. The user can enter text in the text fields and choose shipping method and expiration date in the pickers. Your business and presentation logic are extracted away from your view controller into the interactor and presenter. Custom boundary model structs are used to decouple the Clean Swift components at their boundaries.
In this example, we haven’t looked at the worker and router yet. When your business logic is more complicated, a little division of labor helps. An interactor’s job can be broken down into multiple smaller tasks, which can then be performed by individual workers. When you need to show a different scene after a new order is created, you’ll need to use the router to extract away the navigation logic.
Let’s recap.
What have you done so far?
In this post, you’ve learned:
- The massive view controller problem is real.
- MVC is not a suitable architecture for an iOS app.
- Design patterns and refactoring are just techniques, not architectures.
- Testing is only possible with a sound architecture.
- Good architecture makes making changes easy.
- Organize your code with intents.
- The Clean Swift architecture and the VIP cycle.
- Break down the create order use case into data and business logic.
- Use Clean Swift to implement the use case.
And a reminder on the VIP cycle:
- The view controller accepts an user event, constructs a request object, sends it to the interactor.
- The interactor does some work with the request, constructs a response object, and sends it to the presenter.
- The presenter formats the data in the response, constructs a view model object, and sends it to the view controller.
- The view controller displays the results contained in the view model to the user.
In future posts, we’ll continue with this use case. You’ll learn:
- How to implement the switch to auto-fill the billing address from the shipping address.
- How to use workers to validate the create order form.
- How to save the new order using Core Data when the user taps the Done button.
- How to use the router to navigate to any scene in multiple storyboards.
- How to use TDD to drive a feature.
You can subscribe below to get these future updates, and also get my Xcode templates to start using Clean Swift today.
You can buy The Clean Swift Handbook now to start writing clean swift code using the latest templates, Xcode, and Swift. The PDF ebook has an updated version of this post, and it covers the additional ListOrders
and ShowOrder
scenes, as well as topics on routing and passing data between scenes. There are also additional screencasts to help get you started, and diagrams to give you the big picture. There is currently a special BONUS for a one-month free access to my premium mentorship program. You’ll gain access to more screencasts and tutorials in our private Wistia group.
Finally, if you think this post has shed a new light on iOS architecture for you, I ask that you share this post with your developer friends.
I hope you’ve learned something new and start using it today!
You can find the full source code with tests at GitHub.
the code from https://github.com/Clean-Swift/CleanStore is not working. getting CreateOrderRouter/CreateOrderPresenter/CreateOrderInteractor cannot be constructed because it has no accessible initializers.
Hi fong, I just tried again and it builds and runs for me. What version of Xcode are you using? Could it be because Swift 2.0 or Xcode beta?
UPDATE: I tested CleanStore with Xcode 7.0 and Swift 2.0 and it works.
Aw man! this article is so timely. I have been reading and watching about Clean Architecture for a few months now trying to wrap my head around it and figuring out a way to apply it to iOS development. Can’t wait for the next article in the series.
I had a few questions though that maybe you could assist with:
Q. Would you create a new Scene for each case for example if you had to Edit or Delete an order or would you update the protocols for the Create?
Q. Could you use something like ReactiveCocoa with this architecture?
Hi Marq. I am glad you like my post. Here are my answers to your questions.
Create Order is a distinct use case. So are Edit Order and Delete Order. If these use cases have their own screens, I’ll definitely create a new scene for each.
It’s likely they’ll have more logic than just edit and delete. For example, you may have validation logic on edit, and you don’t want to delete a shipped order.
When I discuss routing in a future post, you can bet I’ll show how to implement edit and delete.
ReactiveCocoa can certainly be used if you want binding-like behavior in iOS. However, you’ll need to be careful not to embed your business logic when you set up your signal. You can call on the interactor when you set up your signal to do the real work. Or, you can also set up your signal in the interactor.
But I found when using Clean Swift, ReactiveCocoa isn’t necessary. One fewer thing to learn. In fact, I found myself writing more and more workers to do individual works. And I have zero pods in some of my projects.
Thanks for the prompt reply, as I’m looking over the sample project/structure i’m a little confused by something. When looking at Uncle Bob’s diagram, for the interactor, there is an input/output interface. In the sample, the input interface of the interactor is defined as the output interface of the view controller (CreateOrderViewControllerOutput). If the interactor implements this interface, why does it need to implement the CreateOrderInteractorInput? It seems that the methods defined in the CreateOrderViewControllerOutput and CreateOrderInteractorInput interfaces mirror each other, why the extra interface?
Indeed, this is exactly what I had in the beta version of Clean Swift. There are two problems that constantly bother me:
1. I don’t know what to name this single protocol. If I call it
CreateOrderViewControllerOutput
, it feels weird for the interactor to conform to a view controller protocol, as inclass CreateOrderInteractor: CreateOrderViewControllerOutput
. Conversely, if I call itCreateOrderInteractorInput
, it feels weird to writevar output: CreateOrderInteractorInput!
in the view controller. It is just so confusing. I just can’t find a good name for it.2. It blurs the boundary between the view controller and interactor. Having
ViewController
in the interactor implementation, or havingInteractor
in the view controller implementation implicitly couples them together. It impliesCreateOrderViewController
andCreateOrderInteractor
have to be used together. But that’s not the case. I want Clean Swift to be a plugin architecture in the Uncle Bob’s way. I want the components can be swapped out and in as long as the protocols are satisfied.Then I experimented with identical protocol implementation with different names to see if Swift can handle it. Voila! It works. Yes, it is redundant. But this is redundancy that I like.
If you look at
CreateOrderViewController.swift
orCreateOrderInteractor.swift
by itself, it shouldn’t impose any restriction on the class of the output, even if it’s just a name in the token.Also, when I declare a method in the output protocol but forget to also declare it in the input protocol, the compiler will warn me because the configurator cannot connect them. It is a nice catch-myself feature.
Again thank you for your quick reply! Wouldn’t something like CreateOrderInput and CreateOrderOutput work. That would remove either of the component names (ViewController and Interactor) from the name and give you something like this:
var output: CreateOrderOutput!
Also this would have the advantage that if the ViewController name were to change or another component was in that role then the interface name wouldn’t need to change.
Also this would change it around slightly where the input would be implemented by the Interactor and the output implemented by the Presenter. However I would think this would mess with your other protocol naming (ViewControllerInput, PresenterInput, etc…)
When a class implements an input protocol, it tells me that it agrees to accept the input methods specified in the protocol and claims to produce the outputs specified in the protocol. So I wasn’t comfortable having a class implement an output protocol.
I just used the view controller-interactor boundary as an example in my comment above. As you rightly pointed out, what about the presenter? We can’t reuse
CreateOrderInput
andCreateOrderOutput
for the interactor-presenter boundary.Yes, it may be overly explicit and redundant. But it certainly is not confusing. Naming variables and methods is a huge part of communicating between programmers. I found that being explicit and the time to copy and paste method signatures outweighs the benefits of saving a few keystrokes.
Hi Raymond,
your VIP pattern seems very interesting. I will use it in my current project.
I don’t want to repeat the topic if it was already posted, but I haven’t seen such a proposal -> Have you thought about unifying boundary protocols into sth like:
ViewInteractorBoundary = ViewOutput = InteractorInput
InteractorPresenterBoundary = InteractorOutput = PresenterInput
PresenterViewBoundary = PresenterOutput = ViewInput
in order not to have duplication when defining Input/Output protocols?
Duplication might be an issue when using code quality analysers. It’s also painful to copy&paste interface between Input and Output.
Another solution to problem could be that Output protocols define conformance to their mirrored Input protocols (due to unidirectional flow):
protocol ViewOutput: InteractorInput {}
protocol InteractorOutput: PresenterInput {}
protocol PresenterOutput: ViewInput {}
Maciej,
I tend to agree with you on the duplicated protocols… I believe Clean Swift was inspired by Uncle Bob’s clean architecture and if you look at some of his sample code he solves the problem in a similar fashion to your suggestion: https://github.com/cleancoders
He uses these types of interfaces (the sample is in java):
InputBoundary
OutputBoundary
Replace with the name of your module. How is it clear which one of those two interfaces should be implemented by the Interactor (UseCase in his sample) or the Presenter? That comes from the very definition of clean architecture that the Interactor is in the center and everything else just plugs into the Interactor. So therefore “input” goes into the Interactor and output comes out from the interactor. Also note that neither of those interfaces include words like “view” or “interactor”.
I had a play with VIPER (https://www.objc.io/issues/13-architecture/viper/) in search for a more modular way to design iOS apps and what became a deal breaker for me was the fact that it seemed to lead to a proliferation of small classes with very very limited responsibilities. For a one man shop that by far outweighs the benefits. I can see how big teams might benefit from modularity to the extreme, but personally I found the code hard to follow and thus hard to maintain. That’s in contrast to Uncle Bob’s model that clearly puts the use case centered Interactor in the middle with simple interfaces for communication through the various boundaries.
Sure, VIPER code becomes extremely modular and reusable, but I couldn’t help feeling that the reusability was sometimes at the same level as reusing single lines of code (ie the same as copy-pasting the code itself), the difference being that these few lines of code were wrapped inside their own classes.
That’s the reason why I see red warning flags whenever I see classes or protocols that simply seem to be unnecessary or not adding any functionality to the design.
In the end of course everyone is free to use whatever they feel works best for themselves. So far Clean Swift is winning the race for me, with small modifications.
Hi Frey,
Uncle Bob’s Clean Architecture slides show parts of the complete system. So you may think the interactor is the center of the universe. But if you put the complete picture together, along with the delivery mechanism being a touch screen that accepts inputs and displays outputs, you’ll also end up with a circular flow of control.
On the other hand, VIPER does put the presenter at the center of the universe, although it has many elements of Clean Architecture.
Whether it’s circular or linear is determined by whether the inputs and outputs are the same. But the unidirectional nature still holds true.
I would argue that using a Clean Architecture for an application shouldn’t depend on the size of the team. But it can depend on the size of the application. The determining factor also is not the time it takes to write the code for the first time. It is the time and ease to make changes.
My previous reply got mangled, the sample should look like this:
He uses these types of interfaces (the sample is in java):
UseCaseInputBoundary
UseCaseOutputBoundary
Replace UseCase with the name of your module.
Hi Maciej,
It has been discussed in the comments, not as a post. The protocol duplication facilitates a ‘plugin’ architecture with a bit of housekeeping.
Thanks for the great post.
I don’t think using a single protocol leads to a coupling. Maybe it’s just a naming problem. I always regard the protocol notion, called interface in java which I think is more inspiring, as the abstraction of concept of physical interfaces from the real world.
Think of USB port. USB standard can be treated as protocol definition ( in fact, it is called USB protocol somewhere) and any slave devices plugged into a computer via USB port can be treated as an concrete implementation of USB protocol. In this case, USB protocol is somewhat neutral, it doesn’t belong to computer (new Macbook even doesn’t have a USB port), it neither belong to slave devices of course (we have USB flash disks as well as SATA disks, flash disks just happen to choose USB to implement).
One thing should be noticed there is USB protocol is called USB protocol (i.e. Universal Serial Bus), not PC-INPUT protocol or FLASH-DISK-OUTPUT protocol. This is nature of a protocol: it defines some constraints for two sides and protocol itself shouldn’t be a component of either side. Computer chooses USB as it’s input protocol and claims to outside world: “I like USB, he’s my spokesman from now on, anyone wants to talk to me should talk to him”, just this, nothing more. Choosing USB to be it’s “spokesman” doesn’t make USB belong to it, USB is still USB, a neutral protocol.
If we put your code implementation to this USB metaphor, the story goes like this: A computer claims that slave device should confirm to COMPUTER-INPUT protocol to communicate with it, and slave device says “The Bible says I shouldn’t know about computer, this is evil, so I only confirm to SLAVE-DEVICE-OUTPUT protocol. God bless me, I love computer in fact”. And you, the God, decide to show mercy on them and help these two poor lovers. Thus you magically make those two protocols identical !
Existence of the God who knows about everything seems to be tricky and dirty in software development, doesn’t it?
Instead, as the God, we should establish the rule, the clause, the protocol. In this way, there is a rule called USB protocol in the Bible and computer says it can accept anyone who confirms to USB protocol. And there is a slave device confirms to USB protocol. But in the end that slave device fall in love with a modern printer because that printer also accepts USB implementations!
The more I code, the less I can write human language (Orz). I hope I’ve made myself understood. If there is anything unclear, please email and let me know, thanks!
Consider some well known protocols (interfaces) Copying, Serializable, etc.
They just define some constrains, some rules, some clauses, nothing more. They don’t hand themselves to any other class, they are just themselves. They don’t know who will implement them, or who will use the implementation of them.
P.S. My email address is nandiinbao@gmail.com
For now, I think just a single protocol called XXXViewProtocol, and making Interactors know about this protocol is fine. On one hand, this architecture is already defined and there is nothing else to plug into interactors output end except for views. And the chance of modifying the architecture should be considerably low compared with the implementation detail. On the other hand, architecture level redesign is rare but unavoidable. My USB metaphor again: USB is designed to transfer data, commands, etc. You just can’t hope to pour some water into it (for cooling down maybe, users are always “creative” and crazy), if there is a new need for a water-pouring compatible USB (can be used to transfer data and pour cool down water), which is really crazy, the USB protocol must be redesigned, that’s unavoidable.
As an architecture, it must has some solid base, there should be something that I can plug other things into. In other words, there is no chance to make every thing as a plugin.
Uncle Bob said “If something changes a lot, it should be a plugin; If something doesn’t change very often, it should be plugged into”.
How about shared protocols named:
– CreateOrderRequest
– CreateOrderResponse
– CreateOrderViewModel
Maybe postfix Connector
Question: What’s your thinking behind putting the shippingMethods in the Interactor instead of having it supplied from the Presenter?
In thinking it thru, it’s definitely a more complicated issue, but shouldn’t it be provided somehow from the Presenter?
Hi Darren, thank you for the question. I wrote a detailed post to answer your question – Reader Question: Should you implement a business rule using the full VIP cycle or a property?
Next question: Let’s say you are implementing an EditOrder Use Case. I would assume that this would use a very similar (or identical) ViewController. Duplicating the ViewController now gives you duplication of work when, for example, styling the ViewController form.
What is your plan of attack for handling (ie: removing) this duplication?
Well, frankly the description is very complicated. There are a bunch of unnecessary protocols, which make these conception very difficult for understanding.
Hi Igor,
I recommend you check out the latest changes to the templates, especially about protocols.
Hi. Enjoyed reading your post. Can I ask why you chose a shared instance of CreateOrderConfigurator as opposed to just a static class? I only ask because I have implemented something very similar with a static class and wondered if there was a particular reason you decided to have a shared instance. Thanks
I used the singleton pattern for
CreateOrderConfigurator
because you only need to hook up the components once for each scene.The
configure()
method is meant to be called just once. If, for any reason, it is called a second time, the code inconfigure()
is structured in a way to release the references from the previous configuration and re-configure everything. This is to prevent a retain cycle and memory leak.If
CreateOrderConfigurator
is not a singleton, you could potentially leak memory and create a retain cycle.Can you show me your static class in a gist? I’ll be interested to see what I can improve in the templates.
Hi,
So in a gist…
To use call Wireframe.prepareUserProfileView(userProfileViewControllerInstance)
What do you think of this approach?
Thanks
Yes. You can certainly use a class method (i.e.
static func
) to implement the configuration behavior.In contrast to VIPER, Clean Swift doesn’t use the wireframe concept. It does the configuration automatically in the Configurator so you don’t have to worry about hooking things up correctly and differently for each scene.
Hi Raymond:
About the configurator singleton, recently I have read in an article about a simpler way and more Swifty way to create a singleton, which may apply to our configurator:
The original configurator:
class var sharedInstance: TasksConfigurator {
struct Static {
static var instance: TasksConfigurator?
static var token: dispatch_once_t = 0
}
Will become like this:
static let sharedInstance = TasksConfigurator()
private init() {}
How do you think?
Here is the link for detailed explanation :
http://krakendev.io/blog/the-right-way-to-write-a-singleton
Hi Andres,
The current configurator singleton has been the most tried and true way of guaranteeing a single instance. I’ve certainly read other alternatives. The current way works very well for me. So I choose to focus on other much more important parts of the Clean Swift architecture over this small details that isn’t going to move the needle.
Now i feel we fall on another wrong side, too many classes and long and hard to read names
Cristi,
True. But a complex app will have a lot of code regardless. If the choice is between a huge file vs many small files. I’ll always prefer the latter. Good architectural boundaries let you focus on just a few files. If it’s a huge file, code inevitably jump all over the place and I am forced to read the whole thing.
Yes, i’ll give it a try anyway, comparing with the objc viper sample this is cleam, that ne has more groups than files. Can you please check if your templates form works? I tried twice and didn’t received them.
Also, why do you call them scenes?
Thanks.
Thank you for bringing it to my attention. I am working with the email list provider to fix it. I will definitely let you know ASAP on the progress. Expect to hear back from me next Monday.
I call them scenes mainly because Apple calls them scenes in their storyboard terminology.
Hey Cristi,
I just re-send the welcome email with a download link to you. Please let me know if you don’t see it.
Can’t download again if download before. Can you show the link in github? Thanks.
Hi bagusflyer,
The download link in the original confirmation email after you subscribed will always point to the latest version of the templates.
Thank you for this article, it really changes the way of thinking about how to program, at least for me!
What about when you want to use the same ViewController to perform more than 1 use case?
My Android colleagues use 1 presenter but 1..n Interactors.
How can I achieve something similar with Clean Swift?
Thanks!
Miguel,
If the business logic is more complicated or if you find your interactor needs to talk to more components such as database, API, …etc, you want to use multiple workers. I wrote more about using workers in this post.
Thank you for your quick answer.
Could you give a little more insight in the router component?
The proper place to call to navigateSomewhere would be the viewcontroller itself, isn’t it?
It is a little confusing for me that the viewcontroller who should only know about what to display, knows something about where to navigate if some action happens, did I get something wrong?
Maybe with a more than one scene example I could see better how this evolves as it gets more complex.
Thank you for your help 🙂
I am going to talk more about the router in a future post. Here is a short answer.
Let’s say you have a List Orders scene and a Add New Order button, when tapped, will display the Create Order scene.
Only the UI should know about the Add New Order button and the fact that it is tapped, so it makes sense to me that the UI should know which scene to be displayed next when the user interacts with it. Since the view controller coordinates the views in the UI, it’s ok for the view controller to invoke
navigateToCreateOrderScene()
.However, the details of how to actually get the Create Order scene on the screen is encapsulated in the router.
I am adding this List Orders scene to the CleanStore sample project, and will have a post on it. But in order to get you to be able to use it immediately, I listed different ways you can present another scene in the router Xcode templates. Hopefully, they are easy to figure out.
I’ve used all of these methods in my projects, so I think it should be a good start.
Thank you for your answer!
I guess If you put it that way it makes sense to let the viewcontroller know about where to go.
Then I think the only problem I see with the relation viewcontroller Router is the data to pass to the next scene. What if it is model data?
Lets say for example that I’m getting from a service 4 attributes, 2 of which have to be presented but the other 2 are needed as data to pass to the next scene. I dont know if going through all the VIP cicle is the good way to go as it won’t be presented but is surely needed by the Interactor in the next scene. What do you think?
I know you will write a post about the Router, If you don’t feel like answering it know I totally understand it. I will find a way around 🙂
It’s just your articles made me re-think a lot about my way of programming and I want to get it as “clean” as I can.
Thank you very much for your time.
Miguel,
I’ll show an example of how to pass data to the next scene. For now, take a look at the router template for how to pass data to the next scene. Here is the relevant code again:
viewController
is the from view controller.someWhereViewController
is the to view controller.output
gives a reference to the interactor.name
is the data you are passing.For your 2nd question, if you just need 2 attributes, consider returning just 2 attributes, instead of 4. You can build an API wrapper service object around the backend API. Don’t make your app fit the API. Make the API fit your app.
And yes, more on the router to come in a future post. And also yes, making your code as clean as possible is the ultimate goal to making your app maintainable.
Question: I am using delegate+closure to get data from REST call and display result in a view. How to fit this process into Clean Swift? Do I need to pass delegate to Presenter? It’s a bit confusing here.
Manh,
You can use either delegate or block for asynchronous calls. Can you elaborate on what you mean by delegate+closure? Maybe post your code?
Hi,
Here is the code with closure. How to rewrite this code in Clean Swift?
in ViewController.swift:
in Entity.swift:
Resolved! My basic mistake. I was passing block of code over the components instead of passing the values (response) only. By the way, I got the idea of Clean Swift more clearly. Thanks for reply.
I also experimented with using blocks across the architectural component boundaries when I designed Clean Swift. I ended up ditching it because:
viewDidLoad()
method do too many things – ask the interactor to retrieve entities and process the results (format the data and display the data).In general, it is best to use explicit protocols to declare boundary methods across architectural components. Blocks can be used within the component, or between the interactor and its workers.
In your example, I would also rename
Entity
toInteractor
. You can create anEntityService
as a worker so that your interactor can communicate with. This has the added benefit that your view controller code doesn’t need to change at all if you decide to use a different entity service (e.g. Core Data vs. over the network).Thanks for advice)
There is an issue from creating files by your templates: after creating CreateOrderViewController.swift I can not see it in custom class field (and later XCode doesn’t show any unwind from CreateOrderViewController). But when I change inside CreateOrderViewController.swift from “class CreateOrderViewController” to “class CreateOrder2ViewController” everything appears normally. So strange. I had tried many times following advices on Internet (delete Derived Data, delete content in /Var/Folder, restart XCode, restart PC…) but no result. For the custom class I can type directly, but I have no idea with unwind. Did you have the same issue or do you know how to resolve?
Xcode has a problem of finding and listing available view controller classes in storyboard. It is a known problem, with or without templates. And yes, I also have to manually copy & paste in the view controller class name. I guess we’ll just have to wait for Apple’s Xcode team to fix it.
I am not aware of any problem with unwind segues. Please keep us updated with your findings.
Hi Raymond, thanks for sharing CleanSwift. I’m finding it very useful coming from a .NET background into iOS. Some of the patterns are similar.
I have a question around handling incoming data from a URL and presenting it in the UI.
Would the correct approach be to call a method on the Interactor from the AppDelegate’s func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject), for example myInteractor.processIncomingData(url: NSURL).
The interactor then turns the incoming data into a ViewModel, then hands over to the Presenter, to then handover to the ViewController for displaying in the UI.
Or maybe a Worker should process the url and then hand over to the interactor?
Thanks!
Hi Ryan,
So another app opens an URL of your app and you want to fetch some data synchronously and display the data to the user.
In this case, you want to first figure out which view controller is handling the first screen to display to the user when the URL is opened from another app. In the view controller’s
viewDidLoad()
method, you can then call the interactor’sfetchData()
method. If you’ve extracted the networking logic of fetching data into a worker, you can invoke the worker to fetch data from the interactor. When the data becomes available, call the presenter’spresentData()
method which then calls the view controller’sdisplayData()
method. The advantage of using the same VIP cycle is that you can use this same flow of control regardless of whether you are showing this view to the user during normal navigation within the app or opening an URL from another app. No code is needed. You just need to add code in the app delegate to decide which view to show.Does it make sense?
Hi Raymond
Thanks for replying. I don’t think I explained the use case clearly enough.
So another app, we’ll call it OtherApp, passes product codes to MyApp by means of a query string in the URL. MyApp reads in the ProductCodes from query string, using the product codes MyApp then gets the ProductName from the Data store then creates and displays the new Order on the screen.
Effectively instead of a user creating the Order, OtherApp is creating the order. The user still has to confirm it though, which is why it must be displayed on the screen.
Thanks!
Hi Ryan,
The situations is similar.
When OtherApp calls MyApp by the means of a URL, MyApp needs to extract the product code from the URL. It can then present the
NewProductViewController
and pass in the product code to it. WhenNewProductViewController
‘sviewDidLoad()
method is invoked, you’ll callNewProductInteractor
‘sbuildNewProduct(code: String)
method. In that method, you can then ask yourProductDataStore
to create a newProduct
object without persisting it. When the method returns toProductDataStore
, you’ll invokeNewProductPresenter
‘spresentNewProduct()
method to format this new order for display to the user. The presenter will then in turn call theNewProductViewController
‘sdisplayNewOrder()
method in which you can set label and text field’s text property. When all is good, the user can tap the Create button. ThecreateButtonTapped()
IBAction method is triggered which will then call theNewProductInteractor
‘ssaveOrder()
method and so forth.As you can see, the VIP cycle is the key to everything. Hope it helps.
Ah yes, makes sense now. Thank you so much.
Hi Raymond,
What about passing data to previous Scenes? I wanted sort of a delegate pattern but setting the viewcontroller as the delegate doesn’t seem apropiate.
I tried setting the interactor of that viewcontroller but it seems kind of messy (viewcontrolleroutput protocol conforming to an external protocol). Furthermore if I want to dismiss the viewcontroller the data passed is not controlled by the router as the action is not a segue.
Also, to make you work, will you talk about API wrappers and core data workers? 😀 Have you thought about the repository pattern?
BTW, I have the same problem with storyboard not recongizing your template classes, it seems to happen only with the templates.
Thank you!
iOS apps are centered around view controllers, really.
When you pass data to a previous scene, it is still best to use the delegate pattern. Set
nextViewController.delegate = currentViewController
. I wouldn’t recommend changing that well established paradigm.The
CurrentViewRouter
is responsible for passing data to another scene. Take a look at the generated router from my templates to see exactly how it works. I left a lot of useful comments in there to help you get started before I have time to write a deep post on routers.I am also going to write a post on API and CoreData specifically. If you take a look at the CleanStore GitHub repository, you can already see the code there. I just need time to write that up.
I haven’t found a way to fix the storyboard class name problem. I’ll welcome any suggestions. 🙂
I found the problem
its here (located in Configurator):
if I move this at the end of the Viewcontroller file, storyboard recognition works.
Hey Miguel,
You are right! I just tested it. This is only a problem with Swift. It works fine with Objective-C version of the templates.
I believe this is an Xcode bug. It has to do with the way Xcode traverses and syntax-checks Swift source files. It has problems when it encounters an extension to a class before the class definition. Or something like that.
It is a small annoyance to me rather than make-or-break at this point. So I’ll just leave it at that. Hopefully, Apple’s Xcode team will fix that. I prefer configuration stuff stays in the Configurator. That stuff shouldn’t need to change. So I don’t want to put it in the View Controller.
But feel free to move it around if that is a problem for you, such as unwind segues that Manh mentioned in an earlier comment.
Hi Ray,
How can I get the objective-c templates?
Hi albertvc10,
After you subscribe using the form, drop me an email.
Oh I’ve just seen the clean store example with exactly what I was asking haha, sorry about that.
Thanks!
I’m new to VIPER architecture in swift, so forgive if I misunderstand something ok.
In relation to routing/wireframe, On the original VIPER flow, Information went from view/viewController-> Presenter -> wireframe/router. According to the https://www.objc.io/issues/13-architecture/viper/ they have the following quote:
“Since the Presenter contains the logic to react to user inputs, it is the Presenter that knows when to navigate to another screen, and which screen to navigate to. Meanwhile, the wireframe knows how to navigate.”
In CleanSwift however, the view/viewController seems to be the one playing this particular role of the presenter. My question is that since the viewController is now involved in the routing, does that make testing more difficult in anyway? In the original VIPER model, the view/viewController can easily be swapped out while other components are tested. But if in CleanSwift the VC is now involved in routing (and not the Presenter), wouldn’t make the view/VC less of a pluggin when it comes to unit testing?
Hi Jay,
You’re right that in VIPER the flow of control is View Controller –> Presenter –> Wireframe. However, the Presenter also talks to the Interactor. Even worse, those arrows are actually bi-directional. The interdependency between the components is kinda messy. It is hard to isolate the components for testing.
You can translate the VIPER quote in Clean Swift terms as follows:
“Since the View Controller contains the logic to react to user inputs, it is the View Controller that knows when to navigate to another screen, and which screen to navigate to. Meanwhile, the router knows how to navigate.”
Imagine you have a button that, when tapped, navigate to a different scene. Who really knows this fact? It’s clearly the view controller because it has the IBAction hooked up to handle that.
The when to navigate is tied to the UI. I don’t think it should be separated out to another component. The how to navigate (i.e. present/popover/dismiss and the transitions) can be extracted to the router.
To force-extract the when to navigate logic to a separate component feels like just moving code around to an unnecessary abstraction layer.
As for testing the view controller’s when to navigate logic, you can simply mock out the router. Then make sure when the button is tapped,
mockRouter.navigateToAnotherScene()
is invoked.As for reusability, it is overrated. Realistically, it’s extremely rare that you would want to reuse the view controller, interactor, or presenter. If there is code to be reused, you would put them in workers. The interactors and presenters from multiple scenes can then instantiate the workers to do the common tasks.
I believe application architecture is more important for code organization and ease of making changes, rather than for reusability. You reuse a very specialized part of the code. You don’t reuse architectural components.
Hope that answer your questions about the philosophical differences between VIPER and Clean Swift.
I guess the original architecture wanted the viewController just as dumb as views.
If button was tapped that should transition screens, VC would only know that a button was tapped. It would not know the reason why it was tapped. That way, the when-to-navigate is not tied to the UI. That way every part does what it supposed to. VC only controls views. Presenter knows all logic. etc etc.
So is this extra abstraction layer unnecessary? Well, I guess right now, i see no disadvantage in your approach. The only difference is that in original architecture, we do not have to test the view/VC as we know its totally dumb. In VIP, some testing may be required there however. But since its only routing, this is easy to do.
Overall your CleanSwift implementation does an excellent job applying VIPER to ios. I wish i had found this site sooner (no clue why it doesnt appear higher on a google search). It would have saved me lots of hours.
It is not hard. The difficult in VIPER is to write VIPER layers in scope of clean architecture principles, without dependencies. It could be really difficult for developers that don’t have enough skills to make really independent viper module layers.
I agree with you on your statement, “that there is nothing hard or difficult to test”.
If you any object is hard or expensive to create, there must be something along the way that can substituted or mocked if you need to test their behavior.
However “The difficult in VIPER is to write VIPER layers in scope of clean architecture principles, without dependencies”, here I’m not talking about 3rd party or outside pod (in terms of iOS app), there must be dependencies whenever you built an architecture, at least on the very basic is on use case level / domain level.
Yes, I also agree that applying SOLID principles, requires lots of practice, and cannot be achieved overnight.
Hi there. Thanks for the terrific post.
My concern is what happens when you deallocate the UIViewController.
As far as i can see, the VC hooks up to the interaction -> presenter -> VC.
if the VC is managed by UINacigationController and lets suppose the VC is on top. When the user hits back, the VC is supposed to be deallocated completely.
However, i might be wrong but, UINavigationController leaves the VC but the VC still has a inward retain count from the Presenter.
Its a chain. And i don’t think it breaks and so get destroyed on back press. Let me know what you think.
Anyways thanks for the terrific post. Its really helpful.
Thanks for bringing that up. I specifically kept the retain cycle in mind when I made the template. That’s why the
output
in the presenter is a weak variable.So when the view controller is deallocated, either dismissed or popped, the interactor and presenter are also deallocated.
Cool! Thanks. My eyes totally missed it, i will definitely take a look and see how i can adopt in the new project.
I had one question about the struct Models used to pass information between the boundaries. Since the presenter is responsible for presenting the information in the viewModel struct, formatted in a friendly manner for the VC, can non-primitive variables be placed in it? Variables like UIImage for instance, to be displayed in a UIImageView. You had mentioned prior that the members of modules should be primitives.
Hi Jay,
That’s a good point. There is some flexibility here.
If it’s a Show Order scene and the order has a limited number of items. You can certainly fetch the images while fetching the orders in the interactor. Then include the UIImage objects in the view model. You can consider UIImage to be a ‘primitive type.’
However, if you are showing a store catalog with many images, fetching all the images in the interactor before you pass the flow of control to the presenter will likely bog down your UI. In this case, I would just put the image URL as String in the view model, and let the view controller create the UIImage objects to take advantage of the caching provided by UIImage and the cell reuse by the table view cells. String is your ‘primitive type.’
What if I need to use NSFetchedResultsController as my table view’s data source?
Obviously, if I need to create NSFRC, this is business logic, so I do it in the interactor. But how do I construct a ViewModel then? What should it contain?
Hi Sergej,
I may do a future post on
NSFetchedResultsController
. But, in the meantime, to give you a few pointers to get started:NSFetchedResultsController
is a controller, not a view controller. So, you’re right. I would try to keep it out of your scene’s view controller and put it in your interactor.To go a step further, keep it entirely in your interactor. The outside world – view controller and presenter – shouldn’t be concerned with how the data is fetched. They only need to know the interactor can give them the data they need. So I would establish an interface in your interactor to facilitate that. Maybe a RESTful one like list, get, update, delete. This should give you the domain model such as an
Order
. You then pass these orders to the presenter.The presenter will turn these orders into
FormattedOrder
objects and pass them onto the view controller for display. Your presentation logic shouldn’t need to change whether you use a traditional data source object orNSFetchedResultsController
in your interactor. It doesn’t, shouldn’t know.Hi Ray,
Thanks for your valuable input,I have gone though whole articles.
I am very impress with VIP(Clean Swift) and I am working one of the current application.
As per Apple iOS design the fetchresultcontroller is tightly coupled with UItableView or UItableViewController which provides the data to TableView from cora data context with all operation like Delete, Swipe between the cell along with animations.
Still I am not able to figure out.I just got stuck about the NSFetchResultsController.
“Which is the place for NSFetchResultsController in VIP Clean swift code.” ?
Hi Mukesh,
Have a look at this repo I did an implementation incorporating NSFetchedResultsController
https://github.com/ankits16/CleanArchitectureWithNSFetchResultController/tree/master
Hello Raymond,
First of all thank you for sharing the code and for your posts. It’s very nice what you are trying to do.
I’m not an expert on Swift and IOS, but one thing that I noticed is that the fetchOrders method reads everything to memory and all orders end up being stored in an array in the VC. The tableview datasource will fetch from there.
The basic examples show us how to use NSFetchedResultsController for that, to avoid reading all entries to memory. The VC is the NSFetchedResultsController delegate and, yes, bad separation of layers, that is not a good approach for clean swift. So, I thought about using the NSFetchedResultsController in the same layer of the CoreDataStore. Maybe CoreDataStore could have the NSFetchedResultsController and perform fetches using it.
Also, you use async fetches for CD, right? For this last approach I think it wouldn’t be good, because the controller (tableview datasource) methods would need instant answers. I think the presenter wouldn’t be useful in this cases.
What do you think? Does that make sense or is it wrong?
Hi Ray,
You asked a very legitimate question! All the approaches you mentioned have their pros and cons. They are suitable in some but not other situations.
I read the data into an array because that’s the simplest approached. It doesn’t take away the focus from demonstrating Clean Swift.
But I can certainly see why you would want to use
NSFetchedResultsController
in some cases.Like you said, I would create the
NSFetchedResultsController
in the CoreDataStore and then provide some methods in the API. I would then try to bubble up those API interfaces up to the interactor level. I believe you would also need to map some of these methods through the VIP cycle so they can be called upon in the table view data source methods in the view controller.It sounds interesting and should be fun to explore further. I would be interested to see your solution.
Hello there. Really interesting posts. Thank you for your work.
I’m trying to implement my architecture after your design but I’m facing a problem. In a view I need to show error messages near each field and a general popover to resume all errors.
Where should I put logic to show error messages?
How would you design validation code avoiding coupling with the view?
How could I create an infrastructure in order to have a common interface for every view to manage error messages coming from validators?
It would be very helpful even just to be pointed in the right direction.
Thank you.
Hi Ant,
Showing an error message can be broken up into two parts:
1. Construct the error message string in your presenter
2. Displaying the error message in your view controller
In your presenter, you can embed the error message string in a view model and pass it to your view controller.
Validation is business logic and should be in your interactor. When you want to trigger validation, let’s say, after the user moves focus to the next text field, you detect this in the view controller. So you want to call a
validate()
method in your interactor.When it succeeds or fails, it passes the result to the presenter. The presenter can construct an error message and pass it back to the view controller.
Finally, your view controller can unhide an error label and set its text to be the error message in the view model.
Hi Ray,
First of all, thanks for this article. It is helping me a lot re-organizing my code make it better. I have some doubt on how to handle data coming from different sources. Would you help me?
I noticed that in your example you have a CreateOrderAPI and a CreateOrderDataCore. How do you manage both? For example:
Scenario: You need to show the user orders that he created. These orders can either be in CoreData or in your backend.
Would the CreateOrderMemsStore have a method doing something like this:
Would this be an OK approach?
Does this look like an OK approach?
Hi Felipe,
Yeah, I have a memory store, a Core Data store, and an API for the Create Order scene for the sample project on GitHub. They are meant to be for a future blog post where I want to show how easy it is to swap workers and service objects using Clean Swift.
They aren’t meant to be used to ‘back up’ each other. But you certainly can do that!
The memory store is really just for testing though. So the method you listed would actually go in the interactor instead of the
fetchData()
method of the memory store. This kind of coordinating logic is ideal for the interactor.Also, the methods are asynchronous, so you would want to check for the presence of the results in the completion block instead of a simple
if...else
.Thanks for the reply, Raymond.
What I am ultimately trying to achieve is complete abstraction from my data layer. I want to be able to write “fetchData()” and have the data returned by my VC from whatever source it is available in. I don’t want my VC to care about where the data lives.
I am thinking about having something like “AbstractDataStore” protocol. A class would conform to it and would deal with deciding which DataStore to call (CoreData, API, Memory). So this class would switch between Workers when it needs to.
That way, I may also be able to also inject that concrete Data Store in my Interactors if I wanted to.
I want total abstraction of my data layer so I can plug different BAAS like Firebase and Parse, for example. Since Parse is getting retired, I could easily switch to the Firebase Repository.
Am I overthinking too much?
If your app’s business logic desires such a fallback approach, that is the way I would do it too. It all depends on what your business logic calls for.
Maybe using the repository pattern approach.
You can have a class that determines which is the best store to use: You could have cache, DB or API store depending on many factors so this class could abstract all this if..else you do and thus the interactor is not dependant on every store it uses.
I will try to implement this using clean store as a base, but any help is appreciated.
Thanks, Miguel. Indeed, it is the Repository pattern I want to implement, also using the Clean Architecture, which I like.
This link here has a good description on how to achieve this: https://www.reddit.com/r/iOSProgramming/comments/4161ya/strategies_for_lessening_dependencies_on/cyzywoj
I will be trying to add this to the Clean Architecture and share my findings soon.
OK, I’ve created a project using Clean Swift but removing the Workers and adding the Repository Design Pattern. I am not 100% sure if I implemented this pattern correctly. Would you guys have a look and let me know?
https://github.com/Solum/SwiftCleanArchtRepoPattern
That will certainly work if your business logic calls for this use case. You can make the interactor agnostic of how it fetches the data. Your interactor can also talk to a FetchDataWorker which will handle the if…else for you.
Hi Raymond,
In your Clean Store project you show how to parse from ManagedOrder to business model Order.
Imagine classes Car and Driver. One car can have many drivers and one driver can drive many cars. With managed objects it is easy to get one from the other. The problem arises when I have to construct the business model object from the managed one.
We’ve thought about passing self when the car is creating every single one of its business model drivers (seems like a lot of processing here to parse) but then if we try to fetch a driver first we have to implement the other approach and it gets kind of order dependant.
How do you manage relationships like this in your business model?
Thank you.
Hi Miguel,
I think NSFetchRequest allows you to fetch relationships too, so you may want to take a look at Apple’s Core Data guide and documentation. But the mechanics of fetching these relationships should only be meaningful in your data store. They shouldn’t be exposed to the interactor and beyond. Watch out for that.
In your data store class, after you fetch, you can have a method like
buildCarAndItsDriversFromManagedObjects()
. Or you can build your model objects while fetching. I think you have to experiment a bit to see which approach works better.Let us know what you find.
Hello Raymond,
Another quick question.
I have a tableview of cells representing data retrieved by a storeworker (l an OrdersListViewController). I want to select one cell and be able to show a new scene which should show the full info of that order.
Since the viewcontroller only knows the orders viewModel data, how can I pass the business model data to the next scene?
I’ve thought of 2 approaches.
1.- Passing the worker between scenes so the new scene can call the worker and get the full business order representation. But it seems messy and unnecessary to call the store again for that already retrieved data but at least I don’t have to create the store again.
2.- Passing the full Order business model to the new scene
Anyway, the problem is to know what order is being selected through the viewcontroller, as it only has viewmodel data and the passing it.
Should I tell the interactor which cell is being selected and then on prepareForSegue pass that business model order? It seems kind of messy to access viewcontroller.output directly as I’m not “outputting” anything. In fact it is like getting.
What do you think is the best approach?
I fail to see what would be a good practice in this common scenario.
Maybe it was not so quick after all 😀
Thank you very much
Hi Miguel,
That’s a very common question I get from time to time. I wouldn’t pass the
ListOrdersWorker
to another scene, because this worker should only contain business logic for the List Orders scene only.I would have a
selectedOrder
variable in theListOrdersInteractor
to save the order associated with the selected cell. Then, in theListOrdersRouter
, where I need to pass the selected order to the Show Order scene, I would just doshowOrderViewController.output.order = viewController.output.selectedOrder
.As you rightly pointed out, it is a little weird to write
output
. I’ve been experimenting with some improvements to the router. One of these changes will be data passing. The other will be the actual routing process. Expect to see an update to the templates on GumRoad.How can you pass the value to the Interactor from the router ? the
output
variable is defined in the viewController with aprotocol
and not with the Interactorclass
right? so actually you cannot pass value directly to a variable defined by a protocol… are you setting a dynamic variable forname
in the Interactor Class?Hi Yari,
A protocol simply lists the properties necessary for the interactor to conform to. The output variable is declared to be a protocol but it is actually a class instance at runtime. You can’t instantiate a protocol.
Hello, nice idea. I just try you architecture.
What do you think about this
Speaker talk in Russian but in the screen all understandably.
Main difference in that architecture – presenter work as mediator.
That’s pretty much the same thing as VIPER. I don’t like the presenter in the center of everything. Soon or later, you’ll result in a massive presenter problem. Also, it necessitates a multi-directional flow of control. It is easy to abuse the presenter. I would stick to the Clean Architecture by Uncle Bob. After all, that’s battle tested for many, many years.
Hello Raymond,
First of all, thank you for the article, it’s absolutely astonishing.
I’ve been wondering how to define the boundaries between the presenter and the view controller but I’ve not reached a conclusion. I know the presenter is responsible for formatting the data that the view controller will show, as you did in your Clean Store example with date formatting. However, should the presenter be responsible for the colors of a label? And what about choosing the content of an image?
To put it in a example, you may be interested in showing red numbers when they are negative, for instance. In this case, should be the view controller who implements the logic of how to show the numbers or it should be presenter’s work?
Thank you.
Hi Oriol,
As always, the answer depends.
If the color is not dependent on the result/error, and it’s a purely design decision, the color should be in the view or view controller.
However, in your case, the color is part of the formatting performed by the presenter. So I would include the color along with the result/error in the view model and pass that to the view controller. Another options is to use
NSAttributedString
to combine text and color.Same thing for images. If there is a green check mark for success, and a red cross for failure. I would embed this information in the view model. I may embed the
UIImage
itself, or just the name of the image such assuccess.png
orfailure.png
.The general rule of thumb is to offload as much formatting work to the presenter as possible. Leave your view controller as dumb as possible. It should just display stuff the presenter passes to it. Keep your presenter busy.
Hi Raymond,
First of all thanks for your time.
Sometimes in my code the viewcontroller deinits but the interactor keeps running (usually because of an unfinished network call) this ends up calling the presenter which calls the viewcontroller causing a nil unwrapping.
Does this happens to you? If so, How do you handle this situation?
I know this has little to do with the architecture and more about good practices i guess ( anyway I learnt a lot of good practices from you and your posts)
Thanks!
Hi Miguel,
As you already mentioned, this could also happen in MVC when you have a reference to an object that has a long running (most likely, asynchronous) task.
Dealing with this problem is not specific to MVC or Clean Swift. You may want to look into
NSOperationQueue
.… or maybe it would be also wise to avoid force-unwrapping. Maybe write a computed property which explicitly checks for a nil-value ? (and if its nil, then just dont discard/dont present what presenter tells to present)
Hi Matis,
In the next update, I’m making the output optional. In the meantime, you can still do
output?.presentSomething()
when it is defined asvar output: SomePresenter!
Hi Miguel,
I just encounter the same problem as yours.
Did you already found the solution to this issued?
Thanks,
Peerapat
Hi Raymond. Thanks again for the post and replies.
I have another question about responsibilities.
let’s say we have to handle UIPanGestureRecognizer. Who must to handle if-else according movement coordinates and store intermediate state of the position and ect:
//positioning logic
if x < maxX {
moveRight()
}
//intermediate states
var startPosition: CGFloat = 0.0
Should I pass coordinates to the Interactor? Then Interactor make this tasks and pass result coordinates to the Presenter. And VC just show.
What if this logic in the UITableViewCell?
Thanks.
Hi Azamat,
It depends. You have to determine whether the gesture handling is business logic or not.
If you are building a drawing app, and the pan gesture is used to draw a stroke on screen. It is business logic because you have to know the color, thickness, …etc. These information should be part of your business logic. In this case, you want to marshal the raw coordinates given by UIKit into the request model. Your business object should also define its own coordinate system.
If the gesture handling is used to implement drag-n-drop, this is view logic and not business logic. So you shouldn’t pass that to the VIP cycle. You want to handle that directly in the view controller if it’s simple. If it’s more complex, you can handle it in a child view controller or subview.
VIPER, It’s learning costs, structural costs, development costs, testing costs, maintenance costs ??
Hi Pikdays,
There’s not a straightforward way to evaluate the cost of an architecture.
Think about it this way. If you create an app without architecture in mind, you are basically making decisions on the fly all the time whenever your view controller grows in size. You’ll constantly have to rethink your class, model, method designs to try to refactor. You can refactor forever. The refactoring cost is large.
On the other hand, Clean Swift is a reusable application architecture that can be used for many apps. You learn it once and use it for any future project. It is easy to tell which piece of code does what. I think that provides tremendous values. Six months from now, you don’t have to trace through a 500 lines in your view controller to understand what an app does. It’s also easier to communicate to other developers your intentions. You can read my other posts on the topics about development and testing to decide for yourself to see if Clean Swift is suitable for your needs or not.
Raymond,
I’m not able to download your Xcode templates. Is the link working ?
Thanks
I couldn’t find your email in my list. After you subscribe, you’ll get an email with a link to download the templates.
Hi Raymond,
I started implementing the Clean Swift architecture just to compare it with the original VIPER architecture. I must say that you did a great job with it and i really enjoy reading your posts. There is one thing i can’t wrap my head around, and that is the duplicate protocol definitions. I understand that the naming can become an issue when using just one interface but i’m confident that a generic name can be found without applying the “input”, “output” suffixes. I find it very confusing as a developer to see that in the Configurator you create an Interactor extension that adheres to the ViewControllerOutput protocol and afterwards in the Interactor class you adhere to a “InteractorInput” protocol that has the same definition as “ViewControllerOutput” protocol. In my opinion this just adds a layer of ambiguity to this line of communication, which should be straightforward and simple. This is just my input (pun intended) on the matter and i think that every programmer should implement the system in a way that best suits it’s needs.
Thank you for your work
Hey! Fantastic series of posts Raymond. Really enjoying using clean Swift. Have a few quick questions I would like to fire at you!
1.) When passing data between controllers using the router what data format do you use? Are you sticking to the structs in the models? In the models file you have request, response and viewModel. Would you recommend creating a similar model such as PassDataModel and putting everything that needs to be passed in there?
2.) You mentioned that all the vars in the structs should consist of primitive types, but what if I have a struct such as Employee with the fields: Name, ID NO, Duties and the field Employer where Employer is another class/struct type. How would you go about representing that? Is it okay to include other structs in the struct and just stuck to primitive types for the view models?
3.) How do you handle routing to a VC that is pushed temporarily and then pops and returns data to the current VC in a delegate method? For example I have a camera VC, I tap the take photo button. First I want to decide if I open the UIImagePicker or the camera. Would you classify this as business logic or would you put it in the router? What I ended up doing is placing this logic in the interactor (checking if the camera has permissions) and then routing from the interactor (I had to create another weak router var in the interactor). I then made the interactor conform to the camera VC’s protocol methods. The reason I did this was because when the image returns I may want to perform some business logic on it so I need it to come straight back to the interactor. Perhaps after I would also want to send it to the presenter to be rotated and such. What are your thoughts on this?
4.) Related to point three, say you hit a button in the VC “post” and there are two possible controllers you could route to. This decision is based on the data in the interactor (domain models). How should this be done? Could you do the business logic in the interactor and then route from there?
Look forwards to hearing from you,
Keke
Hi Keke,
I experimented such a
PassDataModel
and use it in the router. But I didn’t find any benefits over just passing the business object fromScene1Interactor
toScene2Interactor
.First, make sure if you really need to pass the nested relationship in your view model to the view controller. If so, you can have an array of employees in your view model struct. But each of these employee in the array is just another struct containing primitive types. You should not expose the
Employee
class outside of the interactor.That’s exactly what I would do. Yes, the
UIImagePickerController
is a view controller, but Apple owns it. So we shouldn’t force a VIP cycle with it. Instead, we should treat it as a ‘black box’ that just works and provides us an image when it finishes. So what you did is totally reasonable.You should refactor this routing logic in an method in your interactor. Invoke this method in your view controller. Now you have two options to return the flow of control back to the view controller. One, you can just make the method return a
Bool
to your view controller to determine which scene to route to. Two, you can follow the VIP cycle. In either case, I would invokerouter.navigateToNextScene()
in the view controller. After all, in Apple’s terminology, view controllers are a central part of navigation. You create scenes (view controllers) in the storyboard.Hi Raymond,
I wanted to Thank you for this greate series that changed my way of developing. I’m currently applying it into the project I’m working on at the moment.
Regarding the model structs as in the example:
“CreateOrder_FormatExpirationDate_Request”,
“CreateOrder_FormatExpirationDate_Response”, “CreateOrder_FormatExpirationDate_ViewModel”.
I was thinking of another way to create them and wanted to share it whith you to know your opinion.
You are creating them as:
and if we have another Business role for the same Scene “doSomthingelse” it would be another:
How if we change them to be as a tree. One struct for the whole sence with number of sub structs equal to number of roles and each one has three structs for Request, Response and ViewModel.
Then when we user them instead of usering
_
we will user.
“CreateOrder.DoSomthingelse.Request”. Plus I will be more organisied if we have may roles (from my point of view).Looking forward to know you opinion.
Regards,
Thats pretty awesome!
I will be using it 🙂
Hi Ismail,
That’s a great idea.
Raymond, thanks for sharing all this with us.
Not sure if I missed something in your post, but a question came to my mind: what if we have more than one Use Case in a scene? How would that affect the VIP components, the Configurator and Router?
Hi Victor,
When you have a second use case for your scene, you simply add methods to the input/output protocols and implement the methods. For example, for use case 1, you have
doUseCase1()
,presentUseCase1()
,displayUseCase1()
. For use case 2, you havedoUseCase2()
,presentUseCase2()
,displayUseCase2()
. You can certainly find more meaningful names for the methods.You’ll also want to create separate structs for the request, response, and view models for different use cases.
Hello Raymond.
Can you see my project with Clean Architecture + TDD? There are some little differences between your post to my app. For example, I do not implement the Routes layer, but i wish to implement in the future. My project: https://github.com/ronanrodrigo/Recipes
Hi Ronan,
Following Apple’s convention, routing (i.e. presenting and dismissing view controllers) is done in the view controller. But the view controller already has a lot of responsibilities to handle events from the UI and update it. Often, there is logic involved in determining which scene to go to next. I think it’s best to extract the routing to a dedicated router. This way, the responsibilities of the view controller and router are clear.
Hi Raymond. Thanks for the fantastic blog posts!
I have a little confusion on how to get data into a table view. I have my table view setup as normal in my VC. When the view loads I invoke the doGetData() method in the interactor. This method uses a worker that fetches objects from a server using a web API. I now have an array in my interactor i.e. var dataArray: [CustomObject]?. How do I get these results into the table? Say for example I want to display the fields name and address from CustomObject how do I use the VIP cycle to do that? My idea was:
Step 1.) Create a GetData_Response struct with fields name and address.
Step 2.) Iterate though the array in the interactor and create a struct for every entry in the array and put these in another array.
Step 3.) Create another response struct GetData_Array_Response with the field var data: [GetData_Response]?
Step 4.) Pass the struct that contains the array into the presenter
Step 5.) Create a GetData_ViewModel struct with the fields name and address
Step 6.) Iterate the array in GetData_Array_Response and create a view model struct for every entry in the array .
Step 7.) Create another view model struct GetData_Array_ViewModel with the field var data: [GetData_ViewModel]?
Step 8.) Pass the array struct into the view controller
I’m 99% sure my thinking is wrong here. I see in your example you aren’t using the presenter at all for the table view and you just use the { get } methods. But how would you do it in a full VIP cycle and would you use a full VIP cycle for something similar to the example above?
Hi Kex,
What you described is mostly right. But you don’t need to create that many structs. When you get the objects from the worker in your interactor, simply pass them in the response model to your presenter. Then let the presenter to marshal these objects into view model objects before passing them back to your view controller for display.
You can take a look at this sample project I used for my workshop. It illustrates the VIP cycle and also show some advanced error handling techniques.
Hi Raymond. Thanks for sharing all this with us. I’m currently doing an internship as an iOS developper and i’m using your architecture in my project!
I’ve a question about the error management. if we encounter a business logic error (API server not reachable, invalid data, exception, etc) that constrains us to “break” the normal VIP circle (doUseCase1 -> presentUseCase1 -> displayUseCase1), how can I inform the user about this error ? Does my Interactor has to invoke a function like “output.presentError(error: ErrorType)” which in turn (the Presenter) invokes a function like “output.displayError(error: String)” ?
Regards,
Hi Xavier,
Good question. This sample project illustrates one way of handling errors. At a high level, you can have separate methods for handling errors. Or you can “embed” the error handling in the same response and view model objects and then test for success/failure of the optional results array or error.
Congratulations for the article, it’s s great separation of concerns architecture.
There’re only two things I don’t quite like on this design.
I think this configurator could be replaced by an inversion of control system. All it’s doing is manually connecting the boundaries of the artifacts on this architecture. iOC would solve this problem in a better way without the need to add an extra file to each use case. Perhaps the reason for that is because there’s not mature iOC frameworks to Swift so far, not sure though.
Let me know your thoughts about that.
Hi Eduardo,
You probably have a different definition of ‘when it’s required.’ You may be thinking reuse. But architecture design is just as important, if not more. It’s about making something explicit and understandable.
I had all the plumbing littered throughout the view controller, interactor, and presenter when I initially applied clean architecture to an iOS app. So I extracted all this plumbing into the configurator so it doesn’t get in the way of implementing features.
Hi Raymond,
1. When I mentioned “when it’s required”, I meant when there’s more than one implementation at least. This is not a new issue in Swift and already exist in other languages. In other languages this is called single implementation interface issue.
https://www.symphonious.net/2011/06/18/the-single-implementation-fallacy/
http://programmers.stackexchange.com/questions/159813/do-i-need-to-use-an-interface-when-only-one-class-will-ever-implement-it
The issue here is not about to use protocols, it’s about when. You are assuming you will need this protocol in the future so you can switch to any other entity (Class, Struct, etc) that implements this protocol, however at the moment you put this protocol in place you still don’t have this other entity that you believe will use the protocol. This approach of assuming you will need an abstraction and put it in place without having the concrete need for that is what people call abstraction with single implementation issue. The problem with that is that following this approach might result in an application with hundreds of abstractions (protocol, interfaces) that are implemented by one single class and, in this case, it’s completely useless.
2. I got what you did with the configurator, I just mentioned that dependency injection would solve this problem better and in a cleaner way without needing a configurator class.
Please let me know if I’m missing something here…
Interfaces/protocols are used so the dependency arrows between layers point to the right direction (dependency inversion principle) and to separate layers right. It is an architecture issue and also how Clean Architecture is supposed to be. I think that is what Raymond meant.
https://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html
I agree 100% with that but I think I would rather use the concrete implementation until the point a second entity that implements that protocol gets in place, then it would be justified. The trade-off of having hundreds of protocols with a single implementation is the problem that I have.
You’re correct. Renato.
Hi Renato,
“Interfaces/protocols are used so the dependency arrows between layers point to the right direction (dependency inversion principle) and to separate layers right”
That’s absolutely correct, the only problem here is that all these layers are still ONE single layer that was broken down. Extracting a piece of code in a separate file does not make the code part of a new separate layer. Just look the relationship between all those layers in one single scene and you will realize that’s all
about the same thing. It still one single layer that was separated in different files. If you look those interactors and presenters, you will see they only communicate to each other. When there’s a reason to communicate with an external layer in the outside world, that will be done probably through the View Controller of each scene. I think on this example, the scenes are the layers and the ViewControllers the gateway to communicate to the external world.
Also, keep in mind that granularity and abstraction also bring complexity, the same way that having large files does. Having to deal with 5 – 7 files is way more complex than deal with 1. I still in favor of this breaking down but I definitely don’t see all those files in a scene as different domains.
Hey Eduardo!
The way files are organized doesn’t mean there is one layer per ‘scene’. Folder organization is a high level part of the application. In Clean Swift I like that related classes are grouped in one folder, it is easier to find things and focus on use cases. Maybe if there was a need, he would separate differently.
Raymond said: “As Uncle Bob pointed out, group and file names should reveal your intentions for the use cases. It should not reflect the underlying framework structure.” You can find about this also watching uncle bob’s videos on youtube.
Layers are there, you know that by looking at the source code dependencies. The rules to cross layers are being respected, dependencies between them always point inwards.
Sure, more layers, interfaces, classes and tests add complexity. But the idea here is to show the famous Clean Architecture, which does have layer separations and uses the dependency inversion principle to cross boundaries. Also, it tries to respect the SOLID principles. Because of the S, he separated controller and router, for example.
It is the developers’ choice to choose the amount of complexity they want. But still, to cross layers with clean architecture you will need interfaces or you can’t go from an inside layer to an outside one pointing inwards.
Hey Renato!
I didn’t mean there’s one layer per scene because of the way the files are organized. I just see layers as a more high-level abstraction. That’s all.
Forgive my ignorance, Renato. But isn’t the Configurator breaking inversion principle? I mean, COViewController > COConfigurator > COInteractor. I really don’t have deep knowledge of dependency, I just thought that, when a class mention another one explicitly, it is actually depending on that class. Am I totally lost?
Hey Joel, good question, I think you are right. I’m not sure how is clean swift currently handling injecting dependencies. But with the version I got here, I think you are right. Controller (A) depends on Configurator (B) which depends on the Interactor (C), meaning an indirect dependency between Controller (A) and Interactor (C). We should then try to answer the question: Can we use A without C? If B depends on C and A depends on B, then we can’t use A without C. Controller needs an interactor and is using the configurator for having an interactor. For me it is a little tricky to answer this because the configurator is just passing stuff around, but I still think you are right. I would like to here from Raymond what he think about this. For me, considering your point, Clean Swift should do it differently, probably having someone from the outside doing the dependency injections.
Hi Joel and Renato,
The idea of the Configurator is to extract the setup logic out from the VIP components. As a Clean Swift user, one can easily start to implement features without straining his eyes by the extra setup code. The Configurator can do its job most directly by using objects, not protocols, to the VIP components. That’s all there is to it. Objects or protocols. Singleton or regular class. It doesn’t really matter that much.
The principles are guidelines but should be flexible. The principles serve the developers. The developers do not serve the principles. So we shouldn’t play slaves to them. After all, we’re in the business of building apps. We should value practicalities over academics.
I have questions about your article
The readme file doesn’t say much about installing templates. It just says:
make install_teamplates
where do I enter that? In the terminal? Where do I reference the the path of the templates I’ve downloaded and finally are the templates installing legit!?
Hi Khaled,
To install the templates, open Terminal, change to the template directory, and just type
make install_templates
. It’ll figure out everything. You can look at theMakefile
if you want to know where it copies files to.So, what about TDD?
Hi Orkenstein,
Have you checked out my TDD series: Part 1, Part 2, Part 3, Part 4, Part 5?
How would you handle something where the root view controller of your app is a split view controller? Is that a scene with embedded scenes or is there some kind of implied “app” scene? For your example you just have navigation controller and it pretty much sets itself up. With a split view controller the app or something needs do some configuration on the split view (i.e. set a delegate, and setup the button that shows and hides the master view).
Hi Rod,
The simple rule of thumb I use is this. If you have a subclass of
UIViewController
,UITableViewController
,UISplitViewController
, or what not, you should create the Clean Swift components for the scene because you likely have to customize and deal with delegate methods in code. Otherwise, you most likely just need to customize the appearance in your storyboard.Ok. I’m not sure I understand though. If you just create a master detail app using the Apple templates, the app delegate ends up configuring the split view controller and makes the split view’s delegate the app delegate. There is no subclass of UISplitViewController. Something needs to set that delegate and something needs to be that delegate to tell the split view what to do when the master view is collapsed and to setup the detail’s view button that displays the master view when it is hidden in portrait mode. That delegate can’t be set in a storyboard, at least not to the app delegate. What is that something? I’m assuming it shouldn’t be the app delegate. Is there some kind of root scene in this case? Or are you saying that in this case, I need to create the components of the root scene myself and not have the app do it? automatically from the storyboard?
Hi Rod,
I am assuming you are using the
UISplitViewController
as the root view controller in an iPad app. This is similar to using other container view controllers (UITabBarController
,UINavigationController
) as the root view controller in an iPhone app.You don’t normally create subclasses for these container view controllers, certainly not using Apple’s templates to create the initial app skeleton. It sets up the relationships for you in the app delegate.
You have two options.
First, you can continue along and have your app delegate be the delegate for the
UISplitViewController
. You can have your delegate methods in your app delegate to respond to the events. But I would at least pull these delegate methods out to a Swift extension, whether it’s in the same file or a different file. Going a step further, I may create a special object to be the delegate forUISplitViewController
.Second, you can subclass
UISplitViewController
and use it in place of the default one in your storyboard. The setup in the app delegate needs to be modified a little bit to use the new subclass. Since this subclass will always exist because it’s instantiated form the main storyboard or from your app delegate, I would also make it the delegate for itself. Now I can handle all split view controller related events in one place.As for which approach you should take, it depends on how many delegate methods and how much stuff you need to do in them.
Does this help?
Hi great article, I’m trying it on my project. But right now I came up with a question. I have a View Controller with a form inside of it as an embedded View Controller (the form VC doesn’t need any business logic) also there’s a button on the parent VC to retrieve the data from the form, the way I would usually retrieve this data would be through a delegate. What’s your thinking about this should I use just a delegate connecting directly the two VCs or do you have another approach?
Hi Miguel,
First, I would create separate scenes for the parent and child view controllers. This will better isolate the responsibilities.
As for your question, yes, I would also use delegation to pass the data back from the child to parent view controller.
Does this help?
Thanks, it is helpful. I’ll try this straight away
I am in love with clean swift architecture. Will try to use it in all my future apps. Will share my experiences and questions as I go along. Thank you very much.
Hi Vibin,
Thank you for the nice words! I hope Clean Swift can increase productivity and developer happiness.
Hi. I don’t fully understand request(i mean request in model) object. Why we need request if it’s not used? Does it must be related with worker? It would be great if you show an example. Thanks
Hi dima,
Some times the request has no parameters. Other times there are. For example, fetching a list of orders have no parameters. But you can also have a segmented control that allows the user to sort by order date or shipping address and whatnot. Then your request model will have a
sortBy
and/orlimit
to tell the interactor/worker to fetch the 5 most recent orders.I noticed CreateOrderConfigurator.sharedInstance.configure(self) was called in awakeFromNib(). My question is what about there is no xib or storyboard?
Then you can move it to the
init
orviewDidLoad
. Whatever works. 🙂Hi Raymond,
Nice talk. I have something for discussion.
Suppose you have a tcp connection and events can come in anytime, how will you architect it?
Here’s my take:
You will need to have a TCPClient (who will hold on to this tcpclient?) class to send / receive information from the tcp connection. On arrival of new data, you will pass it to a router to handle different response type. e.g. TCPClientResponseNewUpdate, TCPClientResponseNewChatMessage. This response specific classes will be responsible for parsing the response and propagate it up to higher level with specific events (didReceiveNewUpdate:).
Interactor(s) will listen to this event and then subsequently update the presenter, which in turns update this UI.
How does it sound?
Hi Nick,
In your use case, what you described would be outside of the VIP cycle. You want to do all these in some workers/service/manager objects. The VIP cycle handles the boring part. The workers handle the fun part!
Also, there’s nothing to prevent your interactor from invoking your presenter multiple times (i.e.
output.presentEventsFromTCPClient()
). You can also use delegation or notification to bubble up the events.Hi Raymond.
Great article!
Why there is a order array in ListOrdersInteractor?
Should ListOrdersViewController access it directly?
Hi vandilson,
The
orders
array is used to hold the fetched orders, which should be stored in the interactor, as it’s business logic. Your view controller isn’t accessing it directly. Rather, your interactor advertises to the outside world that it stores the fetched orders and its users can access them as a variable.You can also go the traditional way, and provide a getter method
getOrders()
instead. Even better yet, you can stick to the full VIP cycle, and let it propagate to the presenter which then formats the orders into view models before passing them back to the view controller.I just wanted to illustrate some flexibilities in the demo app.
Hi Raymond. Great blog and also interesting discussion in the comments.
Just interested in hearing your reflections on a couple of things.
To me, Clean Swift seems a lot like an implementation of the MVVM pattern. The Interactor is essentially the Model and the Presenter is the View Model, while the view controller is the MVVM controller closely tied to the view.
The first obvious difference between Clean Swift and MVVM is the circular nature of the Clean Swift flow vs the more lateral bidirectional flow in MVVM. It does however seem like Clean Swift in your examples doesn’t stick pragmatically to the circular flow.
Example:
That protocol is identical to the CreateOrderViewOutput. The fact that there is a var in there seems to break this “arrows point in one direction creating a circular flow” paradigm. In one of your examples the view controller directly reads this var from the Interactor, essentially meaning that the flow is actually bi-directional between the View Controller and the Interactor.
I’m not saying this is right or wrong or that the apparent relation to the MVVM model is a discrediting thing, just wonder what your reflections on that are and what benefits you see in Clean Swift vs MVVM.
Someone already commented on the duplicate Protocols between the layers. I have one question about that as well. If one of the main justifications for this extra code is the illogical appearance of only having input protocols and no outputs or the other way around, why not go with the tried and tested pattern of delegation? In that case the Interactor would conform to a UserInterfaceDelegate Protocol, and the Presenter would conform to an InteractorDelegate Protocol. The View Controller could conform to a PresenterDelegate protocol. In that way the names sound logical even with only one Protocol per component instead of two. And that also reinforces the cyclical nature of Clean Swift.
Hi Frey,
About the var on the protocols I agree completely with you, it is only used to pass data between scenes. I think Raymond is working on a new approach. Anyway if you want to look now at an alternative we have created a version of this templates which tries to solve that incoherence at https://github.com/HelmMobile/clean-swift-templates. I don’t know what Raymond thinks about that approach, we are eager to know what he will come up with.
About doubling the protocols I think its a combination of readability, co-working and plugin oriented developing. This way if I work with someone and we specify the protocols before hand, we can easily know what we have to call and what we will receive in a single file. Moreover, if for some reason we wanted to change the cicle or add another component , the output -> input thing will manage that easily in the Configurator because its is build so no one really knows whose input is, or which is its ouput.
In the end is a matter of preference, if you want to change it you are always free to do it I guess 🙂
I think I got your first doubt wrong, I think what you wanted is already asked somewhere in this comment section. You can check this http://clean-swift.com/vip-cycle-or-property/ where Raymond answered in detail.
Sure, I avtually did read that reply. Have to admit that I actually forgot about it when I wrote my comment. But after reading Raymond’s reply to that question, some doubts still remain about vars in thosw interfaces.
Specifically this part raises some concerns: “If you fetch the data asynchronously over the network, Core Data, or any blocking call, you simply don’t have the data until later [so use a full VIP cycle instead of a property]”
But doesn’t that mean that you have now tightly coupled your view controller implementation to an implementation detail of your data source? If for example you go through Raymond’s flow chart and decide on getting the data for your view controller straight from the interactor using a property, it now means that if you decide to later change the source of that data provided by the property so that it comes from a network instead of local storage, it means that you also have to make a change to your view controller AND your presenter. So you then have to change all three compnents of your VIP architecture just because the implementation of the interactor changed. That would seem to render all the work you put in to create multiple protocols to keep the three parts separated useless.
I don’t know if there is a right or wrong answer here, but if your paradigm is to have unidirectional flow of data, then it would seem to make sense to stick to that. If it becomes apparant that some data is really simple and doesn’t require much business logic and doesn’t change often, then group all such data into a struct that gets fed to the presenter. That way you avoid a whole bunch of boilerplate method implementations that do nothing while still maintaining the main paradigm of your architecture intact… Just wondering… Besides, maybe at some later stage you may want to format that data in a different way for presentation, because of localization or other reaaons.
Hi Frey,
Your concerns are entirely valid. That’s why you should stick to the full VIP cycle 99% of the time. CleanStore is simple a demo app, so I wanted to show my readers some flexibilities.
From personal experience, asking developers who only recently start to think about application architecture to implement three methods to do something seemingly simple that they can do in ten seconds can quickly turn them away and back to the massive view controller.
I actually don’t recall using a variable for my own projects because I always stick to the full VIP cycle. Shh…
Hi Raymond and Miguel,
I’ve made my own templates project based on yours. It contains Swift and Objective-C version as also. I’ve removed several extra protocols to fit my feeling of Clean Architecture. 😀
It will be nice if you have a look https://github.com/IvanRublev/CleanTemplates .
Hi Frey and Miguel,
I don’t think Clean Swift and MVVM are similar at all. But let’s not take this to an unnecessarily long conversation. Maybe we can save that for another day.
Yes, the
shippingMethods
variable doesn’t follow the VIP cycle. I did that on purpose. CleanStore is a demo app, so I want to illustrate some flexibilities. You can also introduce agetShippingMethods()
getter method. Or, you can simply go through the full VIP cycle and let the presenter formats the shipping methods into more appropriate view models before passing them back to your view controller for display. Then you’ll maintain the nice unidirectional flow of control.As for the protocol duplication. First, this facilitates a plugin mechanism such that you can swap in a different module. Your app still works because the protocols establish a contract between the modules. The modules must adhere to this contract and provide the methods in order to be used.
Lastly, when you actually use a ‘single protocol’ approach, the names become confusing. I tried that.
Yes, it’s a bit of house keeping work you have to do. But I believe it’s well worth the one-second copy-and-paste.
Hi Raymond,
great blog and a solid reference of Clean Architecture in iOS!
Have you considered adding dates to your posts and an index/archive at the bottom?
It would speed up navigating through your blog and pick topic that one at certain point.
Thanks!
Hi Michal,
I’ll do something about it.
Hello Raymond!
Do you have examples on objective-c?
Something like master – detail with separate store (i.e. cordata / realm)
Thanks!
Hi Dim,
The Clean Swift concept still holds regardless of the language. Only syntax differs. While I can’t promise anything at this point, I do want to show more elaborate examples in the future.
I received many emails from readers who use Clean Swift for their large projects at work, and they are seeing great results like I am. I think it’ll be tremendously useful to have some case studies too.
Is there any project or implementation using networking/web service using this clean swift architecture for reference. Am just starting, My concern now starts with how we should handle error in case of network as we are only passing back the data to the view in the templates.
Hi jyohere,
When there’s an error, it depends on whether you want to propagate the error up to the user or handles it silently. You can bubble up an error message for display just just data. You simply need to add the error in your response model, so your presenter can format it nicely and pass it back to the view controller through the view model.
As for a networking example, you would encapsulate all the API details in a worker/service object. For example, the OrdersWorker has a concrete implementation in OrdersAPI. It’s empty now because I don’t have an endpoint, but you can just use the NSURLSession API to fill it in. Just make it conform the the OrdersWorker just like the OrdersMemStore and OrdersCoreDataStore.
Hi Raymound.
What do you think about replace shredInstance in the Configurator class for
static let sharedInstance = Configurator() ? I think use dispatch_once won’t be necessary because a
let property will be initialised only once.
Hi vandilson,
You could do that or make it a class method now that it’s finally supported. But it isn’t going to move the needle.
Hi, Ray, this post is so helpful, thanks so much for sharing. I just started to use Clean Swift in my project, and I do have a question now: what if the router needs to know some business logic to know where to route? Since the view controller pretty much doesn’t have any business logic in it, and router only talks to view controller, I don’t know what the best approach is for this scenario. Let’s say we have couple of inner states managed by interactor, but the UI is the same, when user clicks the button on view controller, it will route to different view controllers based on those different states. What should I do in Router to implement this and also not mess up with Clean Swift?
Hi Jason,
Thanks for the question. The short answer is you should avoid it.
Let’s walk through a more concrete example. When the user taps the Save Order button, you want to validate the order form on the device before submitting it over the network.
In your
saveButtonTapped()
IBAction method, you could invokerouter.routeToOrderSumittedScene()
. But this method will need to do the validation.So how can you avoid it?
Instead, you can invoke
interactor.validateOrder()
. Let it complete the VIP cycle. When the flow of control comes back to your view controller, you simply look at the view model indicating valid or invalid. And you can respond by routing to different scenes accordingly.Many times when you find that you have to have business logic outside your interactors, it is because you’re trying to skip the steps in the system. It happens to all of us. It comes with practice. When in doubt, ask yourself to see if you can eliminate, not solve, the problem.
Stick to the VIP cycle as much as you can because it is designed to isolate your code and data dependencies. Once you deviate from it, you need to keep the same clean architecture principles in mind.
I hope it clears some things up for you.
Oh, yeah, great helps, Ray! This definitely clears a lot of related problems for me. At first I thought if presenter doesn’t need to do anything meaningful in this cycle, why bother using it? But it’s clear now, I’ll stick to Clean Swift as much as I can, and it does need some practice to get the gist of it. Thanks again!
When you finally take advantage of using the view models, you’ll use the presenter a lot more! 🙂
I think it isn’t a viper! It’s a extended MVC design pattern! What about a presenter layer that conforms to input and output protocols? View doesn’t conform to interactor input protocol and interactor doesn’t know anything about view
I’m not sure what your question is. But no, Clean Swift is not VIPER. Clean Swift does get many inspirations from VIPER though. I think the guys at Mutual Mobile did a fantastic job with VIPER by brining Clean Architecture over to iOS.
What about it?
https://camo.githubusercontent.com/2d4de480082c033f6c59697fbc34c6f6b339ad1e/687474703a2f2f692e696d6775722e636f6d2f7a3042546667692e706e67
Sorry. I made a mistake. You implemented your own design pattern
Hello! I recognized my mistake)! Very good work. I’m often looking for the best practice of the Swift language!
Allowed to write a series of articles on the famous Russian blog about your pattern? People need to know the best practices. Of course, a link to your resource will be!
Absolutely, it’s the free web.
Hey Raymond,
Hope you are doing well. My question is regarding the structure when you have multi language app. I have a doubt if the localization of static strings should be made with the full VIP cycle. I am strictly following the architecture and the single responsibility principle and this makes me think this kind of logic should be in the Presenter, but I am afraid it will make it really big with a boiler plate code. I am eager to hear your thoughts on this and how do you manage the localization in your projects.
Hi Aleksander,
What’s preventing you from just calling
NSLocalizedString()
in your presenters?Hi Raymond,
I have not explained it well. The issue is I have static strings in Storyboard like “About”,”Cancel”,etc and the designer wants me to insert character and line spacing different than the default. As you know the way of doing it is by using NSAttributedString, but Storyboard does not allow you to localize NSAttributedString in Interface Builder, so I have to do it in code. I am wondering if I have to go through the full VIP cycle to put character and line spacing for static Strings that have nothing to do with the model and the backend of my app. I would like to know what actions you would take if you are in this situation.
Hi Aleksander,
Ah, I understand your question now. As you already pointed out, this localization is purely UI and doesn’t involve any business logic. I would just have a single
localize()
method you call inviewDidLoad()
to localize the UI. Alternatively, you may want to move thislocalize()
to your subviews if they grow more complex.Hey Raymond,
fantastic article, really like your comprehensive samples too.
I’m currently struggling with using location services via this pattern. To my understanding, I would implement the logic for getting location updates via the CLLocationManagerDelegate in a Worker and provide this to the interactor in a completionHandler. But as the Worker classes do not inherit from NSObject, it does not conform to the parent NSObjectProtcol. Making the Worker inherit from NSObject gives me a headache initializing the class completion handler property…
How would you tackle this situation? Receive the location in the UIViewController? (is easy, but violates the rules of the pattern).
Thanks for your feedback!
Hi Phil,
Thank you and yes, I tried to be comprehensive and answered the questions people may have before they even asked!
I believe you can mark the delegate methods or protocol with the
@objc
keyword. The compiler usually gives great suggestions and I just clicked on that bubble popup to see what I need to do to make it compile. Works most of the time.And you’re absolutely right. Don’t make your view controller aware of the Core Location stuff.
This WWDC video may also gives you some more insights.
Hey Raymond,
This is the most amazing, well explained architecture article.
I have one query. I am planning to use NSFetchedResultsController to populate my tableview/collectionview. I am bit confused how do I make use of Presenter here to format the data as the NSFetchedResultsController object will be very dynamic.
What flow will you suggest?
Hi Shwet,
I would make sure to refactor and isolate any
NSFetchedResultsController
code into its own interactor/worker. I would not expose the fact thatNSFetchedResultsController
is being used to return data for display outside of the interactor.I may show an example in a future post.
Have a look at this post
https://github.com/ankits16/CleanArchitectureWithNSFetchResultController/tree/master
Are you planning to updating the article for Swift 3 ?
Hi Vikas,
Probably not the post. Maybe a new post? Not sure yet. But I do plan to make the next version of the Xcode templates Swift 3 compatible. If you subscribe, I’ll keep you posted.
Do you know when, more or less, will it happen? I’d really like to use Clean Swift architecture in my next project written in Swift 3.0.
Thanks!
Hi Michal,
I can’t promise a date as I don’t want to paint myself into a corner. There are a lot of improvements I’m making to the templates, so it’s taking a while. I hope to have it ready before the new year.
Hey Raymond,
If my worker needs to fetch data from multiple sources for e.g Local Database and API, then is this the correct way to approach
Hi Shwet,
In your code, I think you need to rename some of the classes and structs.
In essence, you want to establish a common protocol to your data store to fetch your data. You then implement your concrete data stores that conform to this protocol. They should hide the fetch details (i.e. database or API). Your interactor can declare a protocol instead of a class so that you can inject a concrete data store.
Hi,
thanks for the great article, I want to try this in my upcoming project. I have two questions.
1) Reactive
I feel the unidirectional nature of this architecture makes it a perfect candidate to pass signals inbetween the “plugins”.
Did you ever try (and maybe have a link for an example) to make the in-/output protocols propagate signals? If so, what is your outcome? The fact that you do not use it within your example might be caused by unsatisfying experiences, which you might save me from 🙂
2) Model IDs
It has been asked before, but I didn’t get it yet:
Lets say I show some data from a data store, it gets passed through the VIP cycle and the user is able to edit this data and save it afterwards.
As the view/viewController does not know the data model (for instance ID) but only it’s string/number representation, how does the interactor/worker/store know which data has been edited, to update it within the store?
Hi bufFStop,
1) I’ve not tried to mix the reactive approach with Clean Swift myself. In my opinion, it isn’t necessary. But I know other readers of this blog have. Maybe they can chime in?
2) You can save a reference to the entity model being edited in your interactor. When the user edits and saves it, your view controller then invokes the interactor with the changes. The interactor then updates the entity model, and possibly persist it.
Thanks!
Is anyone out there experienced in 1) ?
Hey Raymond
I hope you are doing well.
I am experiencing an issue with the ViewController being deallocated before the VIP cycle is completed. Consider the following scenario when you have a map and you ask the server to fetch back data each time when the user changes the map region based on the new coordinates. If the user decides to go back to the previous scene before the response is received, the ViewController is popped and deallocated. The problem is the VIP cycle is not completed and the response is still passed to the Interactor and Presenter. It crashes at the output signal, because the ViewController is no longer in memory.
Do you handle such cases by making the output optional parameter or you use an alternative solution?
If you look through comments you’ll see I asked something similar, he uses NSOperationQueue.
Hi Miguel,
Can you show me an example how you have used it? It is not like I do not know how to cancel the web requests, but I am having rough time in finding out how to do that without break the architecture principle. Currently I am using AFNetworking 3.0 for handling my web requests and it is isolated in a very abstract layer. Usually it would be very easy to cancel the requests directly from the AFHTTPSessionManager, but only the *APIStore’s are aware of it to some point.
Hi Aleksander,
As a matter of fact I never really solved it, I tried something like you describe using deinit to cancel the requests but I always had some problems. What works for me is what you suggested on your initial question, using optionals.
I think that’s not the best solution because optional means “at some point this can have no value” and talking about connections between presenter -> interactor -> view it sure make sense that it must have value at all times.
If you manage to get something working, please show us the light 🙂
Hi Aleksander and Miguel,
This is a known minor annoyance. Checking for the optional output is the simplest and easiest fix. But it stinks a little. I’ll look into it to see what can be done.
Hi Miguel and Raymond,
I ended up subclassing NSOperation and using it in conjunction with NSOperationalQueue. In the InteractorInput and ViewControllerOutput protocols I put the following functions – func cancelAllBackgroundTasks(). I call the previously mentioned function in the ViewController deinit method. The cancelAllBackgroundTasks() is nothing special, it just cancels all the operations from the operational queue with the cancelAllOperations(). My main concern here is the VIP cycle is not fulfilled, but it is better solutions than accessing my abstract networking layer directly.
PS. One more disadvantage of the above solution is the additional overhead caused by NSOperationalQueue.
Hi Raymond,
I’m having an use case that I couldn’t figure out how to apply your VIP circle, as bellow :
My V uses an open source to display calendar , that requires to setup data-source functions to return information for each date, so it requires return the data immediately in these functions. If I apply VIP circle it will take a delay, V requires I to calculate the data then pass to P to display on V, so I have to reload data for the calendar view, it is extra works, right ?
Can you suggest me a solution for this ?
Thanks.
Hi Dong,
If you make your view controller the data source, it can still invoke the interactor and presenter to retrieve the date information. There is no delay because it is all run in the same thread. More function calls, yes. This is to separate the business, presentation, and display logic. Unless you have performance problem when retrieving the date information, you shouldn’t have any observable delay.
Alternatively, you can extract your data source into its own object, or even make the interactor the data source.
In the following situation:
– A database table holds a column with an image names
– My “ShowImages” scene is supposed to show the actual images
Who is responsible for getting the actual images by the given name, lets say from disk?
Votes welcome for one of the following options:
– Interactor -> ImageWorker
– Presenter
Other options are certainly also welcome, as well as short reason(s).
I think the first one is the correct one.
I would have a imageStore protocol and a BD implementation as imageCoreDataStore then in my worker I would create a path which I would pass to the presenter.
You could pass the UIImage directly but I think its better to abstract from the all rendering frameworks until the view layer.
I am not sure if I got your answer right. What exactly would you pass from Interactor to Presenter?
a) the name
b) a handle to the file
c) the UIImage
If a) or b), who is supposed to create the image?
a) Presenter
b) View(Controller)
Hi buffStop,
It really depends. If your images are small and stored on device, you can create the
UIImage
objects at the interactor/worker level, pass them straight to the presenter, then view controller. However, if you need to fetch images over the network, you definitely don’t want to hold up the UI. You’ll want to fetch them asynchronously, and simply build yourNSURL
objects and pass them on.I think both versions break the responsibility rules. The interactor should not know anything about UIKit (UIImage), while the Prensenter (and even worse the ViewController) shold not know about fetching URLs imo.
Hi buffStop,
I do not think you will break the responsibility rules if you let the view controller to handle the image url. In my opinion the only way you can break the principle is to make the view controller aware of your model and you should not consider the NSURL object a part of your model. It is just a “pointer” to the image that will be downloaded asynchronously.
Aleksander is right about the
NSURL
. It’s simple a convenient representation of an image to be rendered later by the view. Also, if you can imagine anUIImage
as a raw/primitive type, it’s ok to use it in the interactor too. Don’t take it too literally and be more flexible when it comes to responsibility. It’s more about your interpretation than theUI
prefix. Most of the time though, you’ll need to fetch then over the network.Can you provide a working example to use clean architecture with Rx-Swift
Awesome post! I am definitely going to use this architecture in some future projects!
How would you validate the input fields in CreateOrderViewController before creating the Order model in the database/send to backend?
Would you capture the values in the interactor as they are getting set?
Or would the viewController validate them before sending a request to the interactor?
Or send all values to the interactor and let it validate them?
I think this i missing in the CleanStore project.
Thanks!
Its ideal to have the validation logic in Interactor. Incase the validation fails you can directly throw an error thru Presenter.
Moreover if you also have Workers, still Interactor should be the right place for validation and Worker should just be responsible for one particular task.
ViewController shouldnt contain any validation or business logic.
Hope this helps.
I agree! The validation should be performed by the Interactor, since it is business logic.
I think the best pattern would be to have optionals variables on the Request object, sendt it to the interactor and let the validation be handled from there. Then is a validation error is present, then let the full VIP cycle happen to show an validation error in the ViewController.
Hi Mads and Shwet,
You guys figured it out. I love it!
Just want to add that in the request model, you should just pass raw user inputs. The user can enter 914-4j8-u713 for a phone number. You view controller shouldn’t care. The interactor will invalidate it and let the presenter know to return an error message.
Also, if you need to validate phone numbers in other parts of your app, you should extract this validation logic out to a worker. The worker can then be invoked from interactors of any scene that need to validate phone numbers.
Or – just dont use a struct, but an enum:
enum Response {
case .success(data: Data)
case .error(error: NSError)
}
structs are And-Objects, enums are Or-Objects – and usually you have sucess or failure.
Regarding validation – I reckon max length check for an input should be done in-place on the ViewController, since passing the full cycle (VC -> Interactor -> Presenter -> back to VC) is not quite feasible inside shouldChangeCharactersIn:range. What do you think?
Hi Aleksi,
It really depends on what your requirements are. From your delegate method in the view controller, you can invoke the interactor just as easily. Whether you stuff all the logic in the delegate method or use the VIP cycle, it is up to you. I would choose the latter.
I think you may be confused with the VIP cycle and asynchronous operations. The VIP cycle doesn’t make things any slower in your case.
Thanks to Raymond for quite impressive work on the Clean Swift architecture. I’ve been checking the templates + this blog for using them in a new project and it takes some time to acclimatize to, so I decided to draft the same in UML to get a grasp on what’s going on. While the VIP cycle image a the top of this post is cozy and cute and illustrates the flow in high level, there’s more lines than meet the eye actually 🙂 see https://www.dropbox.com/s/5kifxjif2zfbwrj/cleanswift-diagram.png?dl=0
I’ll definitely give Clean Swift a go, and see if it will be a good fit for my project. Meanwhile, it’d be interesting to know if others using Clean Swift templates have shared their work in Github or other places – the available CleanStore example is rather lightweight.
Hey guys,
I have a simple question regarding the Stores. Do you use use 1 store protocol for REST, data persistence(sqlite)? My main concern for using 1 store protocol for both implementation is that when you need some functionality for example in data persistence, which is not required in the REST implementation like tokens, etc. I solved this problem by creating a different protocol called LocalStore. If anyone has stumbled on a problem like mine, please share your way of solving it?
Hi Aleksander,
Your RESTful API has a call like
POST http://example.com/store/123
that takes a POST body of data to update, right? So you can write a method to do this and name itsaveStore(id: String, data: [String: Any])
.Alternatively, you can break up your protocol into two protocols – getter and setter. But I wouldn’t do this.
Hi Raymond,
I think you misunderstood me. In your example you implement the OrderStoreProtocol in OrdersAPI,OrdersCoreDataStore,OrdersMemStore. In my case I have user store protocol which is responsible for all of the REST operations(register user, fetch user, etc), but currently for local data persistence I do not need to implement any of them. I only need to store the token for automatic login at startup, and if I add the saveToken function inside the OrderStoreProtocol, I will have to implement it in UserAPI, where it is obviously not needed. Also if I implement the OrderStoreProtocol in my UserMemStore, I will have to implement the registerUser, fetchUser, etc methods which I do not need in my UserMemStore. To solve this problem I created one more protocol called UserLocalStoreProtocol, that I had implemented in my UserMemStore.
Hi Aleksandar,
Protocol composition sounds like a good solution to your problem.
Wicked framework I’m very impressed with the break down and the templates.
I do have a question about the model in your clean swift store example. Specifically round the DisplayedOrder struct. It is used in multiple Models and I was wondering why you did not create a DisplayedOrder class that could be reused?
cheers
Hey abe,
In my humble opinion he made a separate DisplayedOrder in every scene model, because you might need to display different information/data from the Order class in different scenes. For example when you listing all orders in a table view, you might need only to display the order id and the date. In most cases once you click on an order you redirect the user to a scene, where you show all the details of the order, and in this case your DisplayedOrder instance will contain the full description of the order compared to the ListingOrder scene. Of course you can create a single DisplayedOrder struct with optionals, but personally I think Raymond’s approach is better for clarity.
PS. I was wondering 6 months ago what to use for a big and complicated project, because I was sick of the standard MVC’s and MVP’s, and then I stumbled on this blog. I took a big risk of using it, because it was something new which I have never used, but I must tell you, it is worth it! I am at the final stage of finishing the app, and my biggest ViewController file contains 700 lines of code, something impossible to achieve with standard architectures(and more than half of the view controller file size is in favor of table view and collection view delegates and data sources, that can be moved to a separate file).
Hi Aleksander,
Thanks for jumping in to explain. Well said. I’m excited to hear Clean Swift is working out great for you. Yes, it is paramount in a big project to be able to organize your app. I would add one thing. In addition to reduced file size, it is even more important to know exactly where to find things when you need to. The Clean Architecture accomplishes that goal the best among the alternatives.
Hi abe,
Aleksander’s answer above explains it very well. Basically, different scenes require different data to be displayed. But your approach to lump everything together is not a bad idea either. If many of your scenes display mostly the same data, it may be a better idea.
how to use enum in this architecture.
something like below is not possible.
protocol XYZControllerOutput
{
enum PickerType:Int{get set}
}
but i want to conform it from interactor for uniformity.
Thanks in advance.
Hi Rakesh,
Unfortunately, enums cannot be defined inside protocols. That’s a Swift language thing, not Clean Swift.
Hi .
Can you update the CleanStore Github repo to Swift 3?
Thanks 😀
Hi Luiggi,
I certainly will along with the next big update to the templates.
Hello Raymond,
first of all thank you very much for so much work on breaking down the Massive View Controllers 🙂
I am not sure where to put my question, but it is related to the architecture itself, so maybe here would be the good place.
I am developing an app with the Bluetooth Low Energy usage (CoreBluetooth).
I thought of extracting CoreBluetooth functionalities (scanning for peripherals and later connecting to them) into BLEWorker. But I am not sure how to tight CoreBluetooth events popping out for instance when peripheral is discovered to the Interactor(s)?
Is it a good path or I should rethink the architecture and place the CoreBluetooth functionalities somewhere else?
Thank in you advance for your time!
Best,
Ania
Hi Ania,
I’ve not used CoreBluetooth myself. But I would make the
BLEWorker
the only class to interact with the CoreBluetooth framework. The rest of your app should only invokeBLEWorker
when they need access to status and whatnot. Whatever mechanism – delegation or notification – CoreBluetooth uses to notify your of available peripherals should still be used betweenBLEWorker
and CoreBluetooth.I hope this helps.
Hello, I remain the doubt. You for shippingMethod showed the types from the interactor to the viewcontroller, but to expirationDate if it meets the cycle of viewcontroller -> interactor -> presenter -> viewcontroller. So, supposes that if there is no data to format, this is fine: viewcontroller -> interactor -> viewcontroller, as in shippingMethod
Hi Enzo,
This post may help: http://clean-swift.com/vip-cycle-or-property/
Does anybody know of a bigger open source project that uses this architecture ?
Thank you very useful
Do you know if exist something similar for Android Java?
Valerio
Check Google: https://www.google.de/search?q=android+clean+architecture&ie=utf-8&oe=utf-8&client=firefox-b-ab&gfe_rd=cr&ei=3q18WNvJFrHi8AfpmJ-4Dw
Thank you!
Hello, Raymond, I have just finished your entire blog and the Clean Swift architecture seems awesome. I was wondering of a scenario where you would have a more complex Configurator for the ViewController. Isn’t it enough to have a class function, which can configure the VIP cycle?
I do believe so, thats why I have slightly modified the current templates.
@Raymond, unfortunate that the templates arent in an open github repo, because we cant contribute fixes/additions.
Hi Lyubomir,
The next update will remove the Configurator 🙂
None of your video’s have sound
Hi Raymond,
Thank you for your templates, and blog.
One question though – would it be possible to display create dates for articles and comments?
Can’t agree more. Showing dates for comments can help us better knowing how the codes and ideas grows.
Hi Ray, thank you for this work it is really appreciated. Is there a way to support you so that you can continue creating content regarding these topics?
I inherited a project where the previous developer was experimenting with this structure, regretfully he left before completing the work.
Maybe my question is stupid (I’m newbie with iOS) but I need some help regarding how to handle when the data received from network source is invalid. (e.g.: received a message without text and image content)
As per your article, data-source should not contain business logic neither should the presenter. Does this mean that I should maintain the list of my objects in Interactor even if I already have a list of them in presenter and in the “low-level” class which handles network requests?
It seems to me as quite a lot extra effort.
From the concrete problem I have created a stackoverflow post but didn’t get any response yet.
http://stackoverflow.com/questions/42303618/handling-invalid-firebase-data-with-swift-clean-architecture
Any help would be appreciated. Thanks again.
Hi Yunnyyy,
As always, it depends. 🙂
There are different kinds of errors. At the network transmission level, there could be errors due to packet loss. But does
NSURLSession
tell you about packet loss rate? Nope. That’s low level details thatNSURLSession
, or the socket layer, will try to recover from. You needn’t worry about that.If it’s a malformed JSON response,
NSURLSession
can’t possibly know the JSON format you expect and thus bubble it up to your worker or interactor.In your case, you’re expecting some text and image. Now, you need to determine from requirements that if you can:
As to your second question, data can be temporarily stored in memory, or persisted on disk, in database, or over the network. It’s not about whether data should be persisted in worker, interactor, or presenter. You can store data in memory at any of those places. But you probably want to handle data persistence in your interactor or worker level because it is business logic.
Thank you Raymond,
Well thought response for every case which helped me to see the fault of the design, which is that indexes which are related to database can’t be used on View level (obviously) if there is a possibility that invalid data arrives. Recounting indexes on view level allows me to simply (as you also suggest) disregard the data received in worker. This example also proves that layer separation is of utmost importance.
Keep on with the fantastic work. Thanks again. Cheers.
Hi Yunnyyy,
You’re very welcome. I’m glad you see the problem underlying the problem. While database index may be too implementation dependent, an ID is ok especially with remote networks. Often that’s the only way to refer to an user anyway.
But yeah, separating the layers so that making a change doesn’t affect other parts of the system is the primary goal of a clean architecture.
Hi Raymond,
Im currently working on a project were a viewcontroller+presenter could be reused as they receive the same entities and transform it the same way for different screens. The problem is the interactor as for each screen it should use a different calls and entities.
Lets say the screens show cars, motorbikes, users, etc in the same format i.e. title picture and subtitle. The interactor though handles domain with the pure classes (cars, users, etc) and returns a “categorizable” entity which the presenter transforms depending on its type to a picture + title + subtitle class (viewModel) for the view.
There is a total of 9 screens like that, different calls and entities but same way of showing them.
Did you ever think about a way of building the dependencies on runtime? I mean using a different interactor or presenter or whatever depending on some conditions. If so, what do you think it is the best approach?
Thanks 🙂
Hi Miguel,
For the usage scenario you described, you actually revealed the solution yourself. I also think it makes a lot of sense to categorize – use protocols – the entities you are displaying. Since the entities all share the common traits for display, you can store them as Displayable instead of cars, users, …etc.
But if you ever needs to change this requirements, you’ll have to add customizations in your scenes to accommodate them. But in the meantime, I think protocols are perfect here. There’s no need to get into the Obj-C runtime.
Hey Raymond,
first of all thank you for all the effort you put into clean swift and the whole blog.
At our company we are introducing clean swift for our first few projects to see if it is a suitable option for us for further projects. One problem that I stumbled upon is the following:
I’ve created a scene that displays a custom chart based upon a model of twitter phrases and volume counts. The model is retrieved by the interactor and forwarded to the presenter. The problem here is that I’m creating the chart in SpriteKit, which is implemented as a separate class and located in the common folder, as it might be reused by other scenes. The Chart inherits from SKScene.
What would be the right approach here?
Option 1: Format the retrieved modal in the presenter and initialize the Chart in the ViewController with the ViewModel’s information.
Option 2: Initialize the Chart in the Presenter and forward the SKScene in the ViewModel to the ViewController. The problem I see here is that you advised to only use primitive types in the Model.
Would be great if you could clearify this for me.
Thanks again 🙂
Hey Fabi,
I would do the first approach as it is view representation. Maybe you decide to change the library at some point in the future and as the data represented is the same so you would only need to change the view part.
Some libraries are really difficult to know where they ‘belong’ as they sometimes couple view with business data but in your case it seems its pretty much view data right?
Well that’s my point of view, maybe Raymond has more insight about it.
Hey Miguel,
thanks for the fast reply. That is also the way I’ve implemented it. So can I make the assumption that the presenter is only there for transforming the retrieved Data of the interactor and not really doing anything view related? So if I need to draw something or create UI depending on the retrieved data, I will do this from within the ViewController?
Thanks again.
Well, it is view related as it transforms the data to a model the view can understand. The way I see it, it should format all the data so the view stays as stupid as it can be with no knowledge about the business data and its calculations. The view part should only worry about representing that data and handling the user inputs.
Hi Fabi and Miguel,
I’ve not used SpriteKit, so I don’t know what the models look like. But generally speaking, you’re right. In the presenter, you want to use convert data into primitive types before passing them to the view controller for display. The advantage is that your views can be agnostic such that you can reuse them to display different kinds of data. They’re just strings and numbers.
However, in reality, it may be much more convenient to pass non-primitive types into the views. In some cases, it is much easier to create:
And pass it as is from the interactor, through the presenter, to the view controller and views.
So, don’t take it too literally. There are no rigid rules saying you must use only primitive types. If creating a
Chart
object in your interactor or presenter makes it easier to use in your views, that’s perfectly fine. After all, the view model itself is astruct
, not a primitive type.Hey Raymond,
Having some issues installing the template. I navigated to the directory and ran the command(make install_templates) as per instructions. Yet whenever i create a new project I get the same old template with the default directory structure. Can you help? What am I doing wrong? Current Xcode version 8.2
It is not a project template but a file template. You will see the templates on the File -> New -> File… Menu. Scroll to the bottom.
Hi Raymond,
thanks for your latest and fast response to my question.
In the last days I started a discussion with a colleague about the possibility/usefulness of splitting a view into multiple scenes in certain cases to reduce complexity and improve testability. Did you ever run into the situation of splitting a view into multiple scenes?
Our approach would be to use container views within a view and let each container view be one specific scene. The question I’m asking myself is wether this is in general a good approach from your perspective? (As we are using clean swift only for a short time, I might overlook a future problem)
If it is a suitable approach would you rather:
Have a parent scene that implements the first use case of the screen and also acts as a potential delegate to orchestrate the child scenes within the container views? For example if a certain button is clicked in child A and child B needs to react on this change – this would then be orchestrated by the parent scene.
Split every use case into a child scene, therefore only have container views within the view. Then you could think about an orchestration layer that only has a ViewController & Router to act as a delegate for the child scenes.
I hope my explanation is understandable. What are your thoughts on this?
Hi Fabi,
I have a project where I am using the setup you describe (parent scene orchestrates “sub” scenes. I think there is no (clean) way around in certain situations.
Looks clean and works fine. Let me know if you have questions.
Best,
bs
Hey bs,
perfect, thanks for your reply! Good to hear that in practice this approach looks clean for you – I’ll definitely give it a try and see what I think of it.
regards,
Fabi
Hi Fabi,
Everything you described makes sense. I have tried all of these in my projects and they work very well. It is definitely more preferable to have 3 child scenes with 5 use cases each than having one gigantic scene with 15 use cases. And I also use the parent scene to coordinate/orchestrate event triggers between children scenes. I’ll also add that sometimes I just use a child view controller for the scene with no interactor and presenter, when there’s only display logic and no need for business logic, or when the business logic is already done in the parent interactor, or another child interactor, or a worker.
Hi Raymond,
thanks for your response – glad to hear that both solutions are working and that you tried them out in your own projects!
Hi Raymond,
Thanks for bringing up a wonderful idea to such a long way.
I had one question, why are we not using structure instead of classes while we are creating models. If we use struct we can easily move into including Protocol Oriented Programming making it more loosely coupled.
Eg: Something like below
Hi Vivek,
The models are already implemented as structs. 🙂
In the CleanStore sample app, there’s only one kind of order, so having
Orderable
would not provide any benefit. But if you’re Amazon, I can certainly see some benefits protocols can provide. However, packing and quantity may not make sense for a digital order such as an ebook. Don’t over simplify things and end up making them too generic to be useful.Hi Raymond,
First of all, thank you for introducing such an interesting architecture in the Swift world!
I have started to implement a simple shopping list app based on VIP. I use Firebase as a data store and managed to create a generic data source class which is capable of organizing data into sections based on the added, updated, deleted events from Firebase. This data source class is also implementing some UITableViewDataSource methods (but only at the level of data, no UIKit involved) and can also create changeset objects based on the firebase events. This allows me to easily setup a UITableView and use insert rows, sections, etc instead of just reloading every time when a change occurs.
The hard part is now how to fit this into VIP: I was thinking to:
– keep the data source in the interactor since is it seems business logic
– make a protocol oriented on the data access (rows, sections, item based on IndexPath) and send the datasource under this protocol to the presenter and eventually the view. This way the viewcontroller can easily drive the table view without knowing about the additional methods needed by the interactor to update the data source.
– send events from the interactor to the presenter like presentDataChange(changeset: ChangeSet) and buble them up to the view controller which will call the table view update methods.
Does this make any sense? I’m concerned not to abuse VIP or shortcut it altogether.
Thanks!
Hi Mihai,
If I understand correctly, what you described certainly makes sense. So you would have:
In your interactor:
In you presenter:
In your view controller, you can do:
But not:
This is certainly acceptable to me, as you’re limiting access by protocols.
However, Swift structs are value type. For every small change in the data, you have to pass the whole
postDS
object from the interactor to the presenter to the view controller. This may turn out to be expensive.I think you can do better if you separate the
Firebase
andUITableViewDataSource
into two pieces. Leave the Firebase functionalities in your interactor/worker. Pull out the data source functionalities into another UI worker. You may need to experiment a few solutions to find the right balance. Good luck!Hi Raymond,
Thank you very much for your reply.
At this moment my view controller output protocol has this:
protocol ShoppingListViewControllerOutput {
var dataSource: AnyTableSource { get }
func getItems(request: ShoppingListScene.GetItems.Request)
}
the controller UITableViewDataSource implementation gets quite light since the data source property of the interactor gives me everything I need. The getItems() call will produce eventually ChangeSet events via the presenter so the table view can do what it needs to add, update or remove rows and sections.
I have posted the current project at https://github.com/misumac/shoppinglistvip if you are curios to check the Firebase implementation. Any feedback from you or anyone reading this list would be greatly appreciated!
I still need to read your test related sections, this is my next step.
I have to say that the VIP architecture is really growing on me, with the help of templates everything becomes clear and very straightforward, without the sensation that the architecture is producing too much boilerplate code. Initially I felt that the duplication of protocols is too much, but now I appreciate the fact that one can focus on the task at hand by having all that’s needed in a single file (if you are working on the interactor, you have all the input and output protocols in there, no need to peek at the controller or the presenter).
Hi Mihai,
This is the kind of feedback that delights me. Based on what you described, it sounds like you already get it! The Clean Architecture just feels right and makes happy programmers.
Hi Raymond,
Thanks for replying to my earlier query. Raymond can please present a small example where you clearly explain how this architecture works when something is removed or added to the UI.
For example :
Case 1: Massive ViewController Pattern
1. Consider there is a drop-down Element on the navigation bar of VC-A
2. Selecting an option out of the drop-down, closes itself and displays the selected option text
as navigation bar title.
3. Suppose this drop-down is removed from VC-A and put in VC-B
4. I just need to cut the code from here (ie. VC-A) and paste it in VC-B, along with the UI Component.
5. So the effect of changes are limited to 2 places here.
Case 2: Clean Code Swift Pattern
1. Consider the points 1 to 3 from above
2. Now to work this out I need to make changes to the VC-A input and output protocols
, and then into Interactor-A input and output and at last in Presenter-A input and output.
3. Need to make changes to the VC-Model also
4. And offcourse this will need the UI modification too.
I am sure I am making some mistake here, please enlighten me with the flaw in my solution formation.
Thanks in advance Raymond….
Hi Vivek,
I see where you’re confused. If you just want to spin up a quick and dirty, proof of concept prototype, MVC is the fastest way to get there. Clean Swift won’t help you get there faster. In fact, no architecture will help.
The goal of an application architecture is to provide maintainability, so that you’ll be able to add new features and fix existing bugs easier and faster. You’ll know exactly where to look. The time saving comes later when you need it the most.
Again, if you just need to spin up a quick prototype and will throw it away later, I would use MVC too.
Hi Raymond,
could you maybe give and example like Vivek Mitra did (the clean swift way and the MVC approach) that shows that the clean code approach is easier and faster as you state?
I agree that sometimes Its difficult to find the right place in a code but with search-functions and jump from function to function it’s usually a matter of minutes.
Or maybe you have a “really big” example project to look at. Because my project at the moment has like 40 Viewcontrollers, 3 Storyboards and alone 10 API Rest Classes. All none-UI elements are TDDvdl… Is that kind of project suitable for clean swift?
Hi Marc,
The premise of Clean Architecture is to produce clean code. Clean code is not measured in ease and speed. Try not to focus on the mechanics of navigating your source files. That’s not really the point. That’s the job of an IDE such as Xcode. Clean Swift won’t help you navigate your source files faster. It actually has more files.
However, Clean Swift helps reduce the mental capacity required of you when you implement features and fix bugs. It gets you on a roll and in the zone more effectively. That’s when you realize the speed. This is especially important in large projects. You’ll be able to focus on the task on hand. It makes happy programmers. Happy programmers write better code.
A lot of readers of this blog have told me they wanted to see a large project using Clean Swift. I know that the CleanStore app, while a good illustration of the VIP cycle and unit testing concepts, is relatively small. I’m planning something much bigger and will announce to my subscribers when the final details are worked out.
@Raymond: It would be great if the bigger example project would show how to use common frameworks that, at least on the first attempts, seem crippled by Clean Swift. Like CoreData.
Hello Raymond,
back again for one more question…
1- Sometimes with IOS/swift or with other frameworks and languages it is very common to happen that we have 2 or more active view controllers at the same time and a change in model should affect them all. So, how would you adress this problem with Clean Architecture. I thought about using event bus/radio station to fire events from the data gateway implementations (OrdersCoreDataStore, for example). Then as only the usecaseinteractors talk to the presenters, to listen to events there and update their presenters using the OUTPUT interface, just like it would be without events. But I’m not yet very sure about it. I heard other ideas like listening to events directly on the presenter but the output interface could become useless for some cases and I would like to mantain the clean architecture way with input and output interfaces.
2- Another common thing is to have a Screen/Window (ViewController) as the user input interface for multiple use cases, so how would organize that. Still one class for use case? I think that would be good still, but then listening to events on the usecaseinteractor would not be so good. Maybe creating a special class for the entire view controller use cases group and just to listen to events and to call presenter?
best regards
Hi Renato,
I can envision two scenarios in my head. Assume you have a container view controller P and two child view controllers A and B. In the first scenario, something changes in A that affects B. I would use delegation so A can notify P, which can asks B to change. In the second scenario, if you truly have something changes that affects A and B at the same time, I would extract it into a shared worker W. Both interactors for A and B invokes a method on W and are notified of changes using either delegation or blocks. Inside the delegate methods or blocks, you invoke the output (presenter). The VIP cycle then follows.
I don’t understand your second question. In general, I don’t think it hurts to use separate scenes and employ shared workers.
Ok, thank you!
About 2, what I meant was: In CleanStore example each scene has one use case and one useCaseInteractor. My question was about a scene which has multiple use cases. If then you would have one or multiple useCaseInteractors for that scene.
And, IF you had multiple useCaseInteractors per scene, than relating to question 1, considering that you would have to use delegation/block to see changes in model, if you think that multiple usecaseinteractors is still good.
thx again
Hi Renato,
For each scene, you have one view controller, one interactor, one presenter, to handle any number of use cases. Each use case is represented by a triplet of request-response-view model defined in your
<Scene>Models.swift
. Typically but not always, the number of input/output methods equals the number of your use case structs.understood, thanks for the quick respondse
Thanks you for the amazing post!
I have 2 questions
1) Why don’t you use inits for the Interactor and Presenter because we could set the outputs there?
2) In the viewModel, do I always need to convert the data from the response? I have a very small data object in response. Converting it would have no difference because it would be an object with the exact same properties.
Hi João,
Until we wait for Raymond I can answer with my point of view.
1.- It is a different way of dependency injection but it achieves the same purpose.
2.- You can do whatever you want, the purpose of having to convert is to not couple business data with view data. That is to not have to change everything once view data or business data changes, just how it is mapped.
Thanks Miguel!
What is your opinion on the double interfaces for each component of the VIP vs only three Boundaries, one per component? Like uncle bob does in his clean code samples.
Hi João,
Miguel’s answers would be my answers too. Thanks Miguel. As for the double interfaces, stay tuned for the next update to my templates. 🙂
Hey Raymond,
Do you have some simple examples? I am kind of lost with the too long explanations. Most of the places you havent used workers why are they required? May I ask you something, can you write a tutorial where you download some JSON info an load a tableview. I would like to know where the components go like VC, CustomCells, NetworkManager etc.
Hi john,
The CleanStore sample app primarily shows the VIP cycle to illustrate the concepts of the Clean Architecture. It has simple business logic, so it doesn’t really use workers.
But you can take a look at the different services (memory, Core Data, API) to get a sense of how to integrate workers into your app. Services are workers shared by multiple scenes in your app.
I ran a workshop last year to show how to fetch from an API over the network and parse the JSON response using Clean Swift. This year, I’m planning something much better and will announce it once the final details are set. If you’re subscribed to my email list, you’ll be the first to find out.
Do we map each use case to one ViewController/Scene?
You can have more than one use case per scene. What usually works for me is to define each use case on the Models file in that there is one request one response and one viewmodel per use case. It is not always like this, sometimes I have 2 viewmodels per usecase and sometimes it makes sense to split a big use case in little ones so there is no “rule”. Just try what you have in mind and if it works good, and if not hey at least you will learn something 🙂
Hi Ke,
What Miguel said is correct. There is no rule. It depends on your specific requirements. I’ll just add that when your requirements change, the VIP cycle in Clean Swift makes it very clear what code to change.
I want to load a WebViewController from ViewControllerA. I will be just passing the request to the WebViewController, do I need the entire VIP cycle to load the URL?
Can I use 2 interactors?
If I have an application with a WebViewController and deals with JS calls how does this architecture help. Since all the webview delegates are to be handled in the viewcontrollers.
Do you move all the delegates/ observers to interactor? Like textfields, keyboard observers etc?
Hi John,
Good question!
If you just need to load a web page, you can simply fire up the web view controller from your view controller A. You don’t need a full VIP cycle for the web view controller. That’ll be overkill. Just let UIKit handles the rest. Let the web view controller be part of your view.
But if you need to work with JavaScript to provide some dynamic behavior after loading a web page, I would definitely create a new scene to contain these JavaScript use cases.
As for the delegate and observer methods, you can leave them in your view controller A. Or you can introduce a mediating view controller to conform to them. Inside these methods, you can then trigger the use cases.
Does that make sense?
in the router i think it would be great to pass the sender all the way down to the passDataToNextScene. What do you think?
Also can you update the templates to be more swift 3.0 (the comments are all 2.0)
{ } are in new lines and indentation is different than default xcode
Or if you add the templates to github I can do a PR to fix it.
As we wait for the new release (which I am pretty hyped btw) with updated features from Raymond, this repo has the default braces and other minor changes: https://github.com/HelmMobile/clean-swift-templates you can use it if its more suitable for you, or at least start there.
Hi Joao,
The router will be overhauled in the next template update. Stay tuned.
Raymond, great job on this! I had one question. In your opinion, what are the advantages or disadvantages of enforcing Input/Output protocol conformation using protocol inheritance? For instance, you’d only define the functions in the Input protocol, and the output protocol would inherit from Input. IMHO this looks cleaner as well as makes sure the protocols implement, but are not limited to, the functions needed to facilitate the data transfer?
Thanks for this!
Hi tyler,
I think it’s just a matter of taste. But I’m going to hold off on that because the next template update will change how the input/output protocols are defined and set up.
Raymond, great job on this!
How about NotificationCenter? My approach to take the interactor as the observer (add observer in
init
& remove indeinit
), which works fine in 99%, but it can result crashes if the notification is triggering some “present->display action” before the view is loaded. I don’t want to put the notification logic to viewController, so here is the 2 possible way what I can see:Take the configuration into the viewDidLoad (why it is required to be in
awakeFromNib
? E.g in a TabBarController, theawakeFromNib
is called for each tab, but the viewDidLoad only when the actual tab is displayed. Mostly I don’t need the full VIP cycle to be setup before my view has loaded, right? ):Add a
self.isViewLoaded
check to each display function: In the reactive world, I cannot be sure when the given display function will be called, maybe my viewController is responsible for validating whetherto perform display action or not? E.g:
I prefer the 1st one, and probably I will refactor my whole project to call
Configurator.sharedInstance.configure(viewController: self)
in theviewDidLoad
instead of inawakeFromNib
. Raymond, what do you think?Hi Balazs,
Yes, if it suits your needs better, feel free to move it around. They’re just templates. You may want to change the templates so you don’t have to make the change manually for each new scene you generate.
Having said that, the next template update will change how configuration is done.
Hi, could you explain what’s this code for?
extension CreateOrderInteractor: CreateOrderViewControllerOutput
{
}
Hi Vikko,
The configurator connects the output to the input for each of the view controller, interactor, and presenter. The particular extension you listed connects the view controller output to the interactor. The interactor already conforms to
CreateOrderInteractorInput
. Because of these two protocol conformances, the view controller output is now connected to the interactor input.Hi Raymond,
Thanks for clarifying this. Maybe it’s me because I’m just new to Swift and I’m trying to grasp protocols and protocol extensions alike.
I also have another question, how do I go about saving a data to Core Data if I have something like this:
Order – (an object)
Product – (an object as well)
The Order object contains an orderId and a Product object.
I’m not really sure how to pass this data from the view controller to the worker(interactor) .
Hi Vikko,
If you’re using Core Data, you’re likely using it in multiple scenes throughout your app. So you’ll want to put any Core Data related code in a shared work, or service object, instead of in a specific scene’s interactor/worker. Take a look at https://github.com/Clean-Swift/CleanStore/blob/master/CleanStore/Services/OrdersCoreDataStore.swift for an example.
Hello Raymond,
I am unable to add this template. make install command is not adding this template to my xcode. Can you help me out
Hi mehul,
Try make
install_templates
🙂Hey everyone,
So far I have been experiencing only the bright side of using clean swift architecture. The one and only problem I face right now is the fact you end up with so many files in a large project, and this combined with the immature swift compiler causes build times longer than 5 minutes. How do you deal with this issue to avoid the long building times frustration. I have stumbled on some articles of how to speed the build time in XCode 8/Swift 3 and they recommend to reduce the amount of files in the project. This is something clearly not possible, if I want to not break the architecture.
Hi Aleks,
Hmm… One of my recent projects has upward of 200 files and it’s build time is reasonable. But I have very few Pods. Could your long build time because of other libraries you’re using? I’ve seen long build times with many Pods before Clean Swift too. Try to watch where Xcode spends its time when you build.
Any news on your next Template update?
You were talking about optimizing protocols and configuration…