Tag Archives: UIApplication

How to switch root view controllers in Swift

Here’s how to switch root view controllers in Swift. It comes in handy when you want to instantiate a view controller from your storyboard and display it at arbitrary points in your app.

Imagine a single view application with an additional view controller. Each view controller has a button that switches to the other view controller. To make it more interesting, each view controller is embedded in a navigation controller. The methods to switch to either view controller are called centrally in the AppDelegate.swift file:

In our storyboard, let’s make sure that each navigation controller has a Storyboard ID for manual instantiation. In the above example that’s One and Two respectively.

To call the first method from our first view controller, we’ll do this:

We’ll grab a reference to our UIApplication’s delegate and typecast it to be an instance of AppDelegate. Unlike in Objective-C, there’s no need to import this class into our view controller in Swift. Then we go ahead and call the method.

In our second view controller, we’ll do exactly the same, except for calling the other method in AppDelegate:

Here’s a demo project that shows the above in action:

How to prevent the screen from sleeping in iOS

Screen dimming getting on your nerves? That rancid 5min timeout not enough for testing, or does your app need to stay awake while it’s in the foreground?

Fear not, UIApplication has a parameter we can set to prevent an app from going to sleep, or the screen from going dark. We can set this anywhere in our app:

To make the display adhere to whatever the user has set again, simply change the parameter back to NO.

How to kill your app when it enters background mode

By default, any iOS app we create with Xcode automatically continues running for a short period of time, even if the user puts it in the background and launches a new app. You can even prolong the background execution of an app if your app needs it (for example, finish downloads or long running calculations).

But not all apps need this capability. In fact, if we want to be really nice, we can opt out app in to terminate when it hits the background. It’s really easy to do too: all we need to add is a boolean value into our Info.plist file. It’s called UIApplicationExitsOnSuspend.

Set it to YES and our app terminates as soon as someone presses the home button.

Screen Shot 2015-11-06 at 23.26.02

To add the key, either select your Info.plist file, or head over to your target and click the Info tab at the top (see screenshot).

This is a plist editor, and if you’re not familiar with how to use it, let me introduce you to one of the worst examples of UI design ever – Apple Style:

  • hover over the Key column until you see those little +/- icons come up
  • select the plus icon to add another row
  • double-click the Key part if your row until you can type something in
  • type “UIApplicationExistsOnSuspend” and see it turn into the text “Application does not run in background mode”
  • notice that the type column has changed into Boolean
  • in the Value column, on the far right, find two arrows and change the value to YES
  • that’s it!

Termination Testing

The easiest way to test if this is working is to add a couple of log messages to your AppDelegate file. Find the method stubs for applicationDidEnterBackground and applicationWillTerminate and write yourself a message:

The first method will be called with or without the magic termination key. But the second method will only be called if the app is purged from memory. If you set the key correctly, both methods should be called.

Note that even though the app is killed, it is still visible when you double-tap the home key – but it no longer occupies any memory, nor will it continue to run in the background. As far as I know, this behaviour can only be changed by the user swiping up on an app after a double-tap, or by a hard reset of iOS (hold CTRL+HOME until the Apple Loog appears).

How to link directly to your app’s Settings section

Screen Shot 2015-09-24 at 09.37.14

iOS 8 introduced a new UIApplication method that lets us deeply link to our own app’s section in the iOS Settings app. Previously users had to open the Settings app and hunt for the relevant section, which isn’t always easy to find.

To make use of this handy function, add a Settings.bundle to your app (if you don’t already have one), then open the Settings app with the following method:

It looks a bit complicated because we’re using three methods in one. We could also write those out to make it a bit easier to understand:

In essence we call openURL on UIApplication, with a URL which is defined in an enum constant (UIApplicationOpenSettingsURLString). The latter needs to be converted into a URL via the NSURL method URLwithString. Call this method and iOS will transition to the correct section in the Settings app.

Xcode / Simulator Bug

Note that there is a bug in Xcode that makes the Settings section sometimes show up empty. You can trigger this bug if you deploy from Xcode to Simulator or a real device and then execute this code. You must reboot Simulator or your device for the correctly populated Settings section to show up again.

To prevent any panic attacks from happening, deploy the app from Xcode and stop it. Head back to the app and trigger your method to execute the code. Only then will the section show up as it should. In a real world scenario this isn’t an issue because users won’t ever start your app directly from Xcode.

How to grab a reference to the top most UIWindow

It’s easy to get a reference to the very top window if we write code in our AppDelegate. We can easily refer to it with self.window.

But if you’re writing code in another class then this doesn’t work. Instead, we can use UIApplication and ask for the keyed window – that’s the one currently being displayed:

How to control the Preview Screenshot in the iOS Multitasking Switcher

screenshot

Since iOS 7, when you double-tap the home button, little preview screens are shown above the app icon. Swipe them up and the app is closed. Those preview screens are not live though, they’re simple screenshots that iOS takes before sending an app into the background.

Sometimes it’s not desirable to display confidential information on those preview screens. There is no real way to prevent iOS from taking those screenshots, but it’s easy to detect when an app is sent to the background and quickly change our display before this happens. That way the screenshot is taken of something that we can control.

Method 1: crude yet simple

In its simplest form we could just hide the main window when this happens, and bring it back when the app enters the foreground. We’ll do this in our AppDelegate.m, in applicationWillResignActive and applicationDidBecomeActive respectively:

This will result in our app showing a black screen instead of our “real” content.

Method 2: elegant and subtle

The problem with the above approach is that the transition between the black screen and our app’s content is a plain cut, and because everything else in iOS transitions nicely with fades and slides, the cut looks a little out of place.

One solution is to create our own UIView and overlay our interface with it. UIViews can be faded in and out thanks to their alpha values and a UIView singleton. As an added benefit we get to choose which colour we’d like our screen to be – just in case black isn’t desirable. Let’s use white instead:

This looks more complicated than it really is: in the first method we’ll create a standard UIView called colourView and give it the colour of our choice. We’ll also set the alpha value to 0 so it’s transparent. Since we won’t have a reference to this view we’ll give it a tag so we can identify and fade it out again later. 1234 is completely arbitrary – pick your favourite integer here.

As we bring up the view and add it to the main window’s view it’s invisible. animateWithDuration will fade it in over the course of 0.5 seconds, resulting in a subtle fade in. Now we’ll see white and iOS takes a screenshot – no cuts, no popping.

When we get back from the background we’ll first grab a reference to our view – thanks to the arbitrary tag this is really easy. Next we’ll use the same animateWithDuration method and fade the alpha value back to 0 over the course of 0.5 seconds. Longer durations work fine here too, but anything over 2 seconds gives the impression of lag and slowness.

The animateWithDuration comes in two flavours, one of which gives us a completion block so we can execute code when the fade is done. We’ll take this opportunity to remove our view rather than let it linger there in its transparent appearance.

Method 3: bring your own picture

If a solid colour is not snazzy enough we can replace the UIView with a UIImageView and initialise it with a snazzy picture:

The fade out method is the same. You may need to check device orientation and size here to provide a picture that covers the entire view, or use one that’s 2048×2048 to be on the safe side.

Many developers (including PayPal) choose to grab a screenshot of your app manually at this point and apply a blur effect as if the screenshot is presented through frosted glass.

Demo Project

I’ve added a sample project to GitHub so you can see the above in action: