I found Router in Clean Swift architecture is responsible to navigate and pass data between view controllers. Some samples and articles depict that Routers use segue to communicate with view controllers. What would be the convenient design when I don't want to use any segue from Storyboard. Is it possible to pass data without segue in Clean Swift? If you describe with simplest complete example, would be appreciated.
Article says that you can:
// 2. Present another view controller programmatically
You can use this to manually create, configure and push viewController.
Example.
Let's pretend that you have ViewController with button (handle push):
final class ViewController: UIViewController {
private var router: ViewControllerRouterInput!
override func viewDidLoad() {
super.viewDidLoad()
router = ViewControllerRouter(viewController: self)
}
@IBAction func pushController(_ sender: UIButton) {
router.navigateToPushedViewController(value: 1)
}
}
This ViewController has router that implements ViewControllerRouterInput protocol.
protocol ViewControllerRouterInput {
func navigateToPushedViewController(value: Int)
}
final class ViewControllerRouter: ViewControllerRouterInput {
weak var viewController: ViewController?
init(viewController: ViewController) {
self.viewController = viewController
}
// MARK: - ViewControllerRouterInput
func navigateToPushedViewController(value: Int) {
let pushedViewController = PushedViewController.instantiate()
pushedViewController.configure(viewModel: PushedViewModel(value: value))
viewController?.navigationController?.pushViewController(pushedViewController, animated: true)
}
}
The navigateToPushedViewController func can takes any parameter you want (it is good to encapsulate parameters before configure new vc, so you may want to do that).
And the PushedViewController hasn't any specific implementation. Just configure() method and assert (notify you about missing configure() call):
final class PushedViewModel {
let value: Int
init(value: Int) {
self.value = value
}
}
final class PushedViewController: UIViewController, StoryboardBased {
@IBOutlet weak var label: UILabel!
private var viewModel: PushedViewModel!
func configure(viewModel: PushedViewModel) {
self.viewModel = viewModel
}
override func viewDidLoad() {
super.viewDidLoad()
assert(viewModel != nil, "viewModel is nil. You should call configure method before push vc.")
label.text = "Pushed View Controller with value: \(viewModel.value)"
}
}
Note: also, i used Reusable pod to reduce boilerplate code.
Result:

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With