top of page

Refactoring AppDelegate: Push Notifications Edition


Different types of leaves

When we start out with our iOS development journey and work on our first big project, we often make the mistake of adding all the application level code in a single file, AppDelegate, or at least I did <sad emoji>

Let’s say we want to pull out our Push Notification methods and it’s implementation from the AppDelegate and add it in a separate file (same can go for Firebase initialisation, Location services, App basic checks/initialisation such as Documents directory management, Jail Broken device checks etc), we can do so by following a design pattern called as Factory Pattern. We can use a lot of other strategies available but I personally find this one somewhat simple to start with as other involves somewhat complicated design strategy.

Before be begin, this article will primarily focus on Push Notifications and it’s delegate methods but the same can be used for any of the implementation/s specified before

With that thing cleared up: Let us begin!


 

First, let’s look at this OG way of writing AppDelegate.swift

Here, as usual, we have written our Push Notification initialisation as well as delegate methods inside the same file, which does not looks like a problem, right now, but as the AppDelegate code increases with more and more initialisations such as Firebase, Location Services, Basic Initialisation checks, AppDelegate becomes huge with ever-growing number of lines of code and all the functionalities cluttered at the same place

To resolve this, let’s break AppDelegate up!

Since we’re breaking up our AppDelegate, so each initialisation that is indirectly part of AppDelegate, will have to conform to a type that AppDelegate conforms to, namely UIResponder and UIApplicationDelegate

typealias AppDelegateType = UIResponder & UIApplicationDelegate

Let’s extract all our Push Notification methods into it’s own file:

We will implement only those methods of app lifecycle (such as didFinishLaunchingWithOptions , applicationDidBecomeActive ) which we need for each implementation and let go of the rest which we do not need

Just like PushNotificationDelegate , we can have other files/class for each implementation as follows

Now that our PushNotificationsDelegate is ready, we need a mechanism to attach it to our main AppDelegate. For this, we use Factory pattern.

But before that, we will create a Composite delegate file that will have the responsibility of calling the lifecycle methods of the app for each type of delegate implementation (PushNotificationDelegate, FirebaseAppDelegate etc) and let’s call it CompositeAppDelegate

Finally, our last piece of AppDelelgate refactoring puzzle is a Factory pattern. For this we will use an enum( AppDelegateFactory ) and we will add all the delegate implementation’s instance to it

Finally our App Delegate refactoring is complete !!!

Oh wait, we forgot our main AppDelegate itself

Since now, all our delegate/s implementation and it’s integration has been taken care of (via individual AppDelegates and CompositeAppDelegate), we just need a way to initialise our AppDelegateFactory which will in turn initialise CompositeAppDelegate and call the required app lifecycle methods

So here’s how our refactored AppDelegate will look like

Doesn’t it looks nice? And the best part: if we need to add a new type of AppDelegate implementation (such as Firebase), we just need to remember 2 things

  1. Add new file (and class) for that AppDelegate implementation type and implement the lifecycle methods

  2. Add it’s instance to AppDelegateFactory

We don’t need to make any changes (in most, if not all cases) to AppDelegate or CompositeAppDelegate

The result of this refactoring is a lot less cluttered code and each delegate implementation has it own separate space (file) to add things to which increases readability and makes debugging easier

Related Posts

Comments


bottom of page