How to Make In-app Push Notifications

In case your app needs your own notification system, this article will help you understand, how it works.

Image for post
Image for post
Custom push view

Difficulty: Medium
Read time: 15 min

Basics

So, what is a push notification in details? Some UIView with information, that’s showing on top of any other view in your app. Even when you pushing new screen, it still stays on top.

What else? This UIView definitely has UIPanGestureRecogniser to swipe it away or pull down for extra content and UITapGestureRecogniser to do some work when user tap it.

Sounds pretty easy. But how to make it pin on top of all other views?

Image for post
Image for post

Custom Alert UIWindow

Most commonly, your application has only one UIWindow. That one, which you .makeKeyAndVisible(). Apple SDK says:

The key window receives keyboard and other non-touch related events. Only one window at a time may be the key window.

That means, we can keep our key window and create a new one, above it. We just need override function to detect if touch point belongs to this window. If don’t — touch event will be passed to next underlaying window.

To control our in app push notification animations and actions we need… yes, a controller. UIViewController can play that role.

If your app don’t use SceneDelegate, new window initialisation will be easier via .init(frame: CGRect) . It’s important to set window level .alert because:

Windows at this level appear on top of the status bar.

(That’s not true since iOS 13)

Also, you may’ve noticed, controller creates it’s own parent window and then sets self as rootViewController. Usually it shouldn’t be like that, but here we have a unique story.

Also, there’s an open question: who should retain reference to this controller? For example, it can be AppDelegate or Router entity. Easiest way is to keep it as lazy var pushController = PushNotificationsController() .

Firing notification signal

From any place we can fire notification to show our in-app push (just like with common UNNotificationRequest).

Here comes construction of LocalNotification where I provide it with title, body and userInfo dictionary. Why? Let’s look at the next code snippet.

LocalNotification observer

So, in general userInfo of LocalNotification should provide observer with all necessary data, to define what to do, when user taps push notification. Usually it’s a segue only.

Showing Push Notification

When we need to show notification, we just call show(_ notification: LocalNotification) .

Here, LocalNotification fills CustomNotificationView with all required data. In my example it just provides text for title and subtitle.
Notification window also gets weak reference to a notification button subview.

Configuring CustomNotificationView

Adding gestures:

Layout and slide down animation:

Before animation, notification view should be placed above top window border. Can be done by changing frame.origin.y equal to negative view height. And then, from that position frame.origin.y will change to it’s original value inside UIView.animate closure. For iPhone models with notch this value is view.safeAreaInsets.top and for other models — 8.
You can check out this implementation in repository (link at the end).

Notice, that on animation completion there is delayed hide notification selector perform. Why don’t we use hide UIView.animation with delay instead? At least, because it messes up notification current frame.
Why? Extra task for you 🔍

Image for post
Image for post
Layout for iPhones without notch

That geometry again…

Very simplified work with UIPanGestureRecognizer , without rubber band movement down. Cancelling pan on halfway up — returns view on it’s place, cancelling further — hides notification before selector delayed perform (and cancels this selector).

Finally, proper work for hiding current notification is animation of moving it up behind top border and in completion remove it from superview and if there’s no new notification it’s better to hide window for now.

Advantage:

App can show any important information and no need to worry if user declines app notification request.

Custom push notification can have any appearance, width, height etc. Only limited by your imagination (or UX/UI designer’s).

Disadvantage:

When your phone will get real push notification via APNS, in-app push notification view is blocked. In that way, user can miss some information.

iOS Developer 🇷🇺, Cyprus 🇨🇾

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store