In this blog, we are going to see in detail about the commonly used Communication patterns in iOS. Communication patterns play a major role in the application development. It is essential to know the best practices and the appropriate time to use each pattern. We will see how each pattern works in detail.
Communication patterns in iOS:
The three communication patterns which are going to see here are,
For those who are new to the term communication patterns, here is a short explanation about them which will give you an understanding of what those are.
Delegate: A delegate is an object that acts on behalf of, or in coordination with, another object when that object encounters an event in a program. -Apple
Notification: A notification is a message sent to one or more observing objects to inform them of an event in a program. -Apple
Closures/Blocks: Closures are self-contained blocks of functionality that can be passed around and used in your code -Apple
I hope you would have got some idea what each one is if not no problem we will discuss about each one below, in brief, to better understand how each one works.
How each one works:
Apart from the definition given above, Delegate is most commonly used pattern in most of the Apple frameworks for example like table view, collection view,.. and so on. It helps in notifying about certain events which have been occurred or completed or called.
In order to implement complete delegation pattern, we must have two main things namely
Sender: A sender is the one who declares what are all the delegate methods it supports. ie., we can add one or many methods as delegate methods.
Recipient /s: Recipients are the one who confirms to those senders, and as the result of confirmation to those senders the recipient will have to support/add all or some(in case if the delegate methods are optionally declared by the sender) those delegate methods in their class.
Here to make this delegation works the sender has to notify the recipients using its delegate object whenever the dedicated action has been completed or started or what so ever the state when we want the delegate methods to be performed on the recipients.
Once the sender calls the delegate methods using the delegate, the recipients (one or many) who have currently assigned themselves as the delegate will be called and the recipient can perform their action as per their need.
Few important points regarding delegates:
- Can make use of two-way communication. But mostly we tend to use one-way communication.
- We can pass objects(also custom objects) using delegates in the form or arguments to the delegate methods.
- Delegates produce tight coupling between objects, i.e, the delegating object has a direct reference to its delegate. So It’s easy to trace and identify the flow & control of delegate usage within the app.
Notification communication pattern follows the broadcast model. This way is also used in most of the Apple framework.
In order to implement notification, we again have the following components involved,
Here, The notification communication works with the help of NSNotificationCenter which is a singleton, all the notification is processed throughout this central mechanism.
Before explaining further, to make it, even more, easier for understanding, think how an “FM Radio” works. I will explain the above items with the help of FM Radio.
Sender: Think sender as the FM Station, the work of an FM Station is to host or broadcast the program in a certain frequency. Likewise here the sender object will send/post a notification to the NSNotificationCenter which is like the FM Station who’s work is to broadcast the incoming notification.
Recipient: Think recipients as the subscribers are the listeners of the radio channel(to a specific frequency, likewise wherever we need to be notified of an event in those recipient class we have to add observers for those particular notification type. This will be registered in the NSNotificationCenter as well.
So whenever a sender posts a notification, the recipient will observer will be called and we can perform our actions accordingly as per the need.
Few important points regarding Notifications:
- By default, notifications are delivered synchronously, but we can also post notification asynchronously using NSNotificationQueue.
- It’s acts as one way communication only.
- Cannot able to pass custom objects using notification, instead, we could add the required object inside the user info object that comes along with the notification object.
- Notifications produce loose coupling between objects, i.e, the sender doesn’t know what are all the receivers are listening to it.
Closures / Blocks is an alternative to the delegation, It generally consists of small sets of code combined together and it can also be passed as arguments between methods.
Closures takes multiple forms and each one handles data as follows,
Global functions: It has a name and doesn’t capture any values.
Nested functions: It has a name and capture values.
Closure expressions: Its unnamed with lightweight syntax and capture values from surrounding context.
As of now you don’t need to worry about their types or what capturing values (Capturing Values) means since doesn’t interfere with how it works here.
Closures are functions with no function names and a function keyword. It is mostly recommended to use because of its simplicity of its syntax.
The most used cases of blocks are,
Completion blocks: When you have a time-consuming task and you want to be notified when that particular task gets completed.
Higher order functions: We can use closures as input parameters for higher order functions like filtering, etc,.
One advantage of using closure is that we don’t need to handle memory management, the os will take care of itself.
Best practice, when to use Delegate & Notification:
There is no right or wrong answer on where to use each one of the above ways, this option depends based on your need, here I as far my experience I will share you on what cases you shall choose what kind of option to go with,
- In situations when you want the receiver class to perform all the actions mandatorily.
- If one object needs to talk/communicate with another. I.e., If you want strong coupling/reference between the sender and receiver and so it’s easier for debugging compared to Notification.
- If you don’t want any fraction of time delay on passing the data you can go with delegate since sometimes there is a fraction(very minute) of time delay on using Notification.
- When you want to notify any class(multiple receivers) when certain actions occur on any part of the application.
- If you are about to use multiple listeners without the need of strong coupling/reference between each other.
- When you don’t want to expose any details to the receiver, notification is preferable.
- When you don’t care who are the receivers are.
- My personal suggestion to use notification lesser as possible, it’s not that using notification is wrong, it’s not better suited for debugging purpose.
- For simple functions which have lesser lines of code.
- If a delegate has only one function & it has only small sets of codes as in the above point we can choose to use Closure over/instead of Delegate.
- When you need to perform any task and want the result at any time based on the result computed or fetched like network calls.
In this post, we have seen the commonly used communication patterns namely Delegate, notification and closure in detail. We also saw how the process works and appropriate time of usage. This will give you an insight into these patterns.