Blog

Mobile development: Adding a global button in an iOS app with AppDelegate and SceneDelegate

In this tutorial I’d like to show you how to present UIButton over all visible views in your mobile app. This solution is designed for iOS 13 and newer versions, so it can be implemented in AppDelegate or SceneDelegate.

The solution I am about to present in this tutorial, it should be used only if really needed. In many cases, showing a button via a current View Controller is a better option.

Accessing an app's functionality with a global button

I needed to prepare a framework that would provide access to a functionality from every place in my mobile app.

This could be acheived in many ways. For example with a device shake, specific gesture or, simply, via a global button.

I had wanted my framework to be as simple as possible, so I decided that it will be added just one time, in AppDelegate or SceneDelegate.

This effectively forces my 'access button' to be displayed in all available views.

Adding a UIButton to an app's views

So first, I needed to get what view is on top of the app stack. This can be achievied in iOS 13 thanks to this method:

UIApplication.shared.windows

The just-created button can be added to all views just like this:


let button = UIButton()

for window in UIApplication.shared.windows {

window.addSubview(button)

}


Keeping the UIButton's top position

There is yet another important thing. If you want to keep your button on top, you need to change its position:

button.layer.zPosition = +1

If you don’t do this, the button will hide under the presented views and will be neither visible, nor accessible.

This is not all. Before implementing your button in AppDelegate, you should know that using touchUpInside can be tricky.

This is because user gestures are captured by View Controllers. So even if you add a button to the top of a presented view, its actions cannot be captured in AppDelegate (or SceneDelegate).

Both

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool

and

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions)

are called before the views are loaded. So adding your button should be delayed if you want to capture its actions. This can be done thanks to the following method:

DispatchQueue.main.async

After its implementation, your button's actions should be accessible just the same way as if you have prepared it in View Controller.

Of course, DispatchQueue can be tricky, so the best way in my opinion is to test your functionality on real devices.

This is it, and thanks for reading!

Check our latest product - it's based on our experience of managing over 50-people strong company. The tool we're missing as a small company and not an enterprise.

humadroid.io is an employee and performance management software. It's an unique tool allowing everyone to be in the loop - by having up to date info about co-workers, time-off, benefits, assets, helping with one-on-ones, being a go-to place for company-wide announcements.

Check out humadroid.io
Top

Contact us

* Required fields

The controller of your personal data provided via this contact form is Prograils sp. z o.o., with a registered seat at Sczanieckiej 9A/10, 60-215 Poznań. Your personal data will be processed in order to respond to your inquiries and for our marketing purposes (e.g. when you ask us for our post-development, maintenance or ad hoc engagements for your app). You have the rights to: access your personal data, rectify or erase your personal data, restrict the processing of your personal data, data portability and to object to the processing of your personal data. Learn more.

Notice

We do not track you online. We use only session cookies and anonymous identifiers for the purposes specified in the cookie policy. No third-party trackers.

I understand
Elo Mordo!Elo Mordo!