Apple has provided us with the NSNotificationCenter class (or simply notification center) in the
Cocoa library that implements the Observer pattern. There are three primary functions that we can
perform with this class. They are:
- Add an Observer
- Notify the Observer
- Removing an Observer
·
Lets start off by looking at how we would add an observer
Adding an Observer
In the examples for this post, we will be using the
following function to add an observer:
func
addObserver(notificationObserver:
AnyObject,
selector notificationSelector:
Selector,
name notificationName:
String?,
object notificationSender:
AnyObject?)
This function has the following parameters:
- notificationSelector: This is the function to call when the notification is posted. This method must accept one argument which is an instance of the NSNotification class.
- NotificationName: This is the name of the notification that we wish to register with. We generally want to define this name as an application constant so if we ever need to change the name we only need to change it in one spot. If this value is nil, the notification center will not use the name to determine if an observer should be notified when a notification is posted.
- notificationSender: This is the object which the observer wishes to receive notifications from. If this value is nil, the notification center will not use the sender to determine if an observer should be notified when a notification is posted.
Now lets look at how we would use this function to add an
observer:
NSNotificationCenter.defaultCenter().addObserver(self,
selector: "actOnButton1:", name: Constants.BUTTON_1_CLICK_NOTIFY, object: nil)
In this example, we are adding a new observer where the notificaitonObserver is the current
object, the notificationSelector is
a function named actOnButton1, the notificationName
is defined by the BUTTON_1_CLICK_NOTIFY property of the Constants class and the
notificationSender is nil.
Now lets look at how we would notify the observers.
Notify an Observer
In the examples for this post we will be using the following
function to post a notification to the observers.
func
postNotificationName(notificationName: String,
object notificationSender:
AnyObject?)
This function has the following parameters:
- notificationName: This is the name of the notification we wish to post. We generally want to define this name as an application constant so if we ever need to change the name we only need to change it in one spot.
- notificationSender: The object which is posting the notification.
Lets look at how we would use this function to post a
notification.
NSNotificationCenter.defaultCenter().postNotificationName(Constants.BUTTON_1_CLICK_NOTIFY,
object: self)
In this example, we are posting a new notification where the
notificationName is defined by the BUTTON_1_CLICK_NOTIFY
property of the Constants class and the notificationSender
is the current object
Before we put it all together in our example, we need to
show one more function of the notification center. This is how to remove an observer.
Removing an Observer
In the examples for this post we will be using the following
function to remove an observer.
func
removeObserver(notificationObserver:AnyObject)
This function takes one parameter, which is:
- notificationObserver: The object that is registered to receive the notification.
Here is an example of how to use this function to remove an
observer.
NSNotificationCenter.defaultCenter().removeObserver(self)
In this example we are removing the notifications for the
current object. Now lets show how we
would put these together to use in our applications.
NSNotification Example
In our example, the main screen will have two buttons where
each button will send a different notification when they are tapped. We will then have two observer classes that
will register for the notifications and print messages to the console when the
notifications are received. The first
thing we need to do is to crate a constant class that will contain the
notification names.
Constants.swift
Here is the code for our Constants.swift class
class Constants {
static let
BUTTON_1_CLICK_NOTIFY = "hoffman.jon.button.1"
static let
BUTTON_2_CLICK_NOTIFY = "hoffman.jon.button.2"
}
In this class, all we do is define two static constants that
define the names of our notifications.
If we ever need to rename our notifications, we can rename it in this
one spot rather than all over our code.
Observer Classes
We will create two observer classes. These will be named Observer1.swift and Observer2.swift. These observer classes will subscribe to
receive the notifications when our buttons are pressed.
The Observer1.swift
class will subscribe to the notification named BUTTON_1_CLICK_NOTIFY, while the Observer2.swift class will subscribe to
both the BUTTON_1_CLICK_NOTIFY
and BUTTON_2_CLICK_NOTIFY
notifications.
Lets look at the code for the Observer1.swift class first.
import Foundation
class Observer1{
init() {
NSNotificationCenter.defaultCenter().addObserver(self, selector:
"actOnButton1:", name: Constants.BUTTON_1_CLICK_NOTIFY, object: nil)
}
@objc func actOnButton1(notification: NSNotification) {
println("Button 1 pressed from Observer1")
}
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
}
In the Observer1.swift class we start off by creating an initiator. In that initiator we use the NSNotification.defaultCenter()
.addObserver() function to subscribe to the notification that named with
the Constants.BUTTON_1_CLICK_NOTIFY
constant. When we subscribe to the
notification we set the selector to the actOnButton1:
function. This function will be called
every time a BUTTON_1_CLICK_NOTIFY
notification is published.
In the actOnButton1() function, we simply write a message to the console
to let us know when the function is called.
Notice that we use the @objc
attribute with this function. The
notification center requires that we use this attribute with any function that
we want to use to receive notifications.
Finally we define a de-initiator
for our Observer1.Swift class. In this de-initiator we use the NSNotificationCenter.defaultCenter().removeObserver()
function to remove the observer. We want
to make sure that we remove the observer when we destroy an instance of the
class.
Now lets look at the Observer2.swift class.
import Foundation
class Observer2 {
init() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: "actOnButton1:", name: Constants.BUTTON_1_CLICK_NOTIFY,
object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "actOnButton2:", name: Constants.BUTTON_2_CLICK_NOTIFY,
object: nil)
}
@objc func
actOnButton1(notification: NSNotification) {
println("Button 1 pressed from
Observer2")
}
@objc func
actOnButton2(notification: NSNotification) {
println("Button 2 pressed from Observer2")
}
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
}
The Observer2.swift
class is pretty much the same as the Observer1.swift class except that we
subscribe to both the BUTTON_1_CLICK_NOTIFY
and the BUTTON_2_CLICK_NOTIFY
notifications.
Finally lets look at the ViewController
class that will publish the notifications when the buttons are tapped.
ViewController.swift
The Viewcontroller class contains two functions that are
tied to UIButtons. These functions will publish the
notifications when the buttons are tapped.
These functions are shown here:
@IBAction func
button1Pressed(sender: UIButton) {
NSNotificationCenter.defaultCenter().postNotificationName(Constants.BUTTON_1_CLICK_NOTIFY,
object: self)
}
@IBAction func
button2Pressed(sender: UIButton) {
NSNotificationCenter.defaultCenter().postNotificationName(Constants.BUTTON_2_CLICK_NOTIFY,
object: self)
}
Within these functions, all we do is use the NSNotificationCenter.defaultCenter().postNotificationName()
function to post the notifications when the buttons are tapped. Each time a button is tapped and the
notifications are posted, the functions in the Observer1.swift and Observer2.swift
instances are called.
In this post we saw how easy it is to implement the Observer
pattern in Swift using the notification center that Apple provides. I hope this post helps you understand both
the notification center and the Observer pattern.
You can read more about design patterns in Swift in my forthcoming book Mastering Swift published by Packt Publishing.
You can read more about design patterns in Swift in my forthcoming book Mastering Swift published by Packt Publishing.