Combine Framework Beginner Tutorial in Swift - Working with NotificationCenter

Note: If you are a beginner and you find it difficult to understand things written in this article. Feel free to ask questions on my Reddit page or Twitter.

Remember, you can do it. 😉


Combine is so helpful in processing the data. It’s something you will enjoy using once you know the benefits and it’s proper usage.

If you haven’t started using Combine or don’t know how to use Combine in your application. This article is for you. My next few articles are going to be all about Combine, so subscribe to stay updated.

What is Combine?

Combine is a framework in Swift used for handling asynchronous events and produce customized results by combining multiple operators. Multiple operators here means that we can do various types of processing by writing smaller and easy to read code and shape the values according to our needs.

Combine works in two main ways:

  • Publisher

  • Subscriber

Publisher is a protocol used for delivering values to one or more Subscribers. You can create your publisher too, and we’ll learn about that as well in my upcoming article. Subscriber is also a protocol, used for receiving values from Publisher.

Combine with NotificationCenter

NotificationCenter comes with the Publisher object built-in; we just need to start using the operators.

Let’s dive in with examples for better understanding.

let name = Notification.Name("com.publisher.combine")

let publisher = NotificationCenter.default
    .publisher(for: name)

With this call publisher(for:) you will receive a publisher object, but we need a subscriber to receive elements from the publisher. So, we'll start with sink(receiveValue:) to receive values from our publisher.

let name = Notification.Name("com.publisher.combine")

let cancellable = NotificationCenter.default
    .publisher(for: name)
    .sink { note in
        print(note.userInfo!["SearchString"] as! String)
}

NotificationCenter.default.post(name: name, object: nil, userInfo: ["SearchString": "test"])

/*
 Output:
 test
 */

Note: You can run all the code shown in this article in the playground, just don’t forget to add the import Combine line on top of your file.

You can see that we have received an output test, and this is done with the help of sink(receiveValue:) function which gives us the notification object, and with that, we retrieved our newly published value done by the post(name:object:userInfo:) function.

If you have worked with NotificationCenter previously, you required a selector to execute your function, but with the help of Combine framework, we can receive our values on the go and do modifications without declaring functions separately. The only thing you need to keep in mind is the life of the property you have declared.

Let’s look into modifying our published data with the help of operators.

What are Operators in Combine?

If you look into the extensions of Publisher you can see a lot of function declaration, which can be used to modify the values received from the Publisher, and those functions are termed as Operators.

How to use them?

Dive in.

let name = Notification.Name("com.publisher.combine")

let cancellable = NotificationCenter.default
    .publisher(for: name)
    .map({ ($0.userInfo!["SearchString"] as! String) }) // Introducing Map
    .sink { value in // "value" is of type String now
        print(value)
}

NotificationCenter.default.post(name: name, object: nil, userInfo: ["SearchString": "test"])

/*
 Output:
 test
 */

In the code above we have used map(_:) to change the type and process the value we received from the notification.

Next, when we call .sink { value , the type of the value is String instead of Notification. The type changes depending on the return values of the previous operator called.

Now, lets try the filtering the values which contains numbers in it. We can do this with the help of the operator filter(_:).

let name = Notification.Name("com.publisher.combine")

let cancellable = NotificationCenter.default
    .publisher(for: name)
    .map({ ($0.userInfo!["SearchString"] as! String) })
    .filter({ $0.rangeOfCharacter(from: CharacterSet.decimalDigits) == nil }) // Filter values containing numbers
    .sink { value in
        print(value)
}

NotificationCenter.default.post(name: name, object: nil, userInfo: ["SearchString": "test"])

Thread.sleep(forTimeInterval: 1) // Wait for 1 Second

NotificationCenter.default.post(name: name, object: nil, userInfo: ["SearchString": "test100"])

Thread.sleep(forTimeInterval: 1) // Wait for 1 Second

NotificationCenter.default.post(name: name, object: nil, userInfo: ["SearchString": "testing"])

/*
 Output:
 test
 testing
 */

If you look at the output, there are two lines printed, whereas we posted three notifications.

So, what happened here is that our second notification with value test100 was filtered out with the help of the filter(_:) operator.

If you want to cancel the subscription, you can do that by calling cancel() function on your subscriber.

E.g.

cancellable.cancel()

So, this is how we can make use of Combine with NotificationCenter. There’s a lot more to learn in Combine framework and I’ll be coming up with a bunch of more articles about Combine. So if you enjoyed reading this article and want to stay updated with my upcoming articles, then Subscribe now.

If you have any suggestions or questions, Feel free to connect me on Twitter or Reddit. 😉

To read, Combine - Processing Values with Operators in Swift, Click Here.

Combine - Processing Values with Operators in Swift

How to avoid Thread Explosion and Deadlock with GCD in Swift?