Make Your Swift Controllers Reusable and Efficient
Written on
Chapter 1: Introduction to Reusable Controllers
In app development, it’s common to need the same UI element across various screens. For instance, consider the case where you want to display a custom tab or navigation bar. The standard approach involves creating a distinct custom UIViewController for this navigation bar, which you then incorporate as a child view controller. In this article, I will demonstrate how to minimize the boilerplate code associated with managing this child view controller, making it highly reusable.
Keep in mind that when I mention reusing the child view controller class, I am not implying the reuse of a single instance of the controller.
For illustrative purposes, let's consider a scenario where your tech lead assigns you a task on a Monday with a Friday deadline. The objective is to finalize the login and registration flow, as outlined in the documentation below: The introduction page presents two options—login and register. When a user selects either option, the Phone/Otp confirmation page appears. After confirming their phone, the user is directed to either the registration page (if they came from the register action) or the main application page.
You might be tempted to dive right into the task and pass an enum or flag to the OTP page to indicate the user's origin. While this solves the immediate issue, if additional requirements arise later, you’ll find yourself adding more flags, leading to cluttered and difficult-to-maintain controllers.
So, what’s the solution? Take a moment to reflect over your coffee. I’ll be here when you’re ready to explore my solution.
The answer lies in crafting a Reusable ViewController. You might be thinking, “Talk is cheap; show me the code!” Let’s delve into the details.
Our PhoneConfirmation Controller should function like a service, allowing us to use it wherever phone confirmation is needed. Upon confirmation, we can redirect to multiple screens. Below are the components we’ll use:
- IntroductionController
- PhoneConfirmationController
- RegisterController
- MainPageController
- LoginCoordinator — this manages all navigation throughout the login and registration process.
First, we need to establish our application’s initial controller, which we will handle through the SceneDelegate configuration.
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
var loginCoordinator: LoginCoordinator?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let scene = (scene as? UIWindowScene) else { return }
let window = UIWindow(windowScene: scene)
self.loginCoordinator = LoginCoordinator(window: window)
self.loginCoordinator?.start()
window.makeKeyAndVisible()
self.window = window
}
}
In this code, the SceneDelegate creates a LoginCoordinator associated with our window and configures the initial controller to be the IntroductionController, which is displayed first when the app launches.
Now, we need to design the controllers and establish navigational paths between them.
Chapter 3: Video Resources
A tutorial on creating reusable buttons in Swift.
Learn how to implement generic and reusable API calls in iOS development.
Conclusion
In summary, the approach of reusing UI elements across multiple screens can significantly enhance your code's maintainability. By extracting navigation responsibilities from controllers and utilizing closure callbacks, you create more organized and reusable components.
Thank you for taking the time to read my insights on software development, coffee, and general topics. I appreciate your support and hope to make your reading experience valuable.