The Controller

Tying everything together now is straightforward. We need to port in the message-sending logic, as well as the error handling; and we should be done:

class PostMessageController: ComposeViewControllerDelegate {

Store references to the view controller, validation controller, and networking controller as follows:

    let viewController = ComposeViewController()
let validator = MessageValidator()
let networking = PostMessageNetworking()

init() {
viewController.delegate = self
}

The delegate method implementation: The implementation here is the core of the logic that ties the view layer to the model layer (which is the responsibility of the controller layer).

This method validates the message, attempts to send it, and updates the view layer to provide feedback to the user through the state property of the ComposeViewController:

    func composeViewController(_ viewController: ComposeViewController,
attemptToSend message: String) {
if let error = validator.validate(message: message) {
viewController.state = .error(error)
return
}

viewController.state = .sending
networking.post(message: message) { (success, error) in
if let error = error {
viewController.state = .error(error)
} else {
viewController.state = .default
}
}
}
}

PostMessageController has been implemented as a true controller, in the MVC sense. It showcases how one controller can and should orchestrate the communication between the view layer and the model layer. Implementing this design pattern will ultimately improve the quality of your code base.