Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Mastering iOS 14 Programming
Mastering iOS 14 Programming

Mastering iOS 14 Programming: Build professional-grade iOS 14 applications with Swift 5.3 and Xcode 12.4 , Fourth Edition

Arrow left icon
Profile Icon Mario Eguiluz Alebicto Profile Icon Chris Barker Profile Icon Donny Wals
Arrow right icon
€41.99
Full star icon Full star icon Full star icon Full star icon Half star icon 4.7 (15 Ratings)
Paperback Mar 2021 558 pages 4th Edition
eBook
€32.99
Paperback
€41.99
Subscription
Free Trial
Renews at €18.99p/m
Arrow left icon
Profile Icon Mario Eguiluz Alebicto Profile Icon Chris Barker Profile Icon Donny Wals
Arrow right icon
€41.99
Full star icon Full star icon Full star icon Full star icon Half star icon 4.7 (15 Ratings)
Paperback Mar 2021 558 pages 4th Edition
eBook
€32.99
Paperback
€41.99
Subscription
Free Trial
Renews at €18.99p/m
eBook
€32.99
Paperback
€41.99
Subscription
Free Trial
Renews at €18.99p/m

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Product feature icon AI Assistant (beta) to help accelerate your learning
Table of content icon View table of contents Preview book icon Preview Book

Mastering iOS 14 Programming

Chapter 2: Working with Dark Mode

We all love it…well most of us do anyway, and those who do have been asking for it for a while now too. Apple first took the plunge into Dark Mode with macOS Mojave back in 2018, not only changing the way users interacted with the OS but also paving the way for developers to build native dark-themed apps for the first time.

Dark mode for iPhone wasn't announced until WWDC 2019, but we all knew it was coming, and with everything that AppKit had offered, we knew we were in for a treat with what UIKit would have to offer.

In this chapter, we'll cover everything you need to know to get up and running with dark mode in iOS and iPadOS; everything from taking an existing app and making the necessary adjustments to support dark mode, to all the little hidden extras that we can add in when building our app to ensure we give the user the best possible experience. We'll also touch on best practices too – taking note of the little things we can do that allow Dark Mode in UIKit to make our lives so much easier from the start.

The following topics will be covered in this chapter:

  • What is Dark Mode?
  • Working with views in Dark Mode
  • Working with assets
  • Further exploring Dark Mode

Technical requirements

For this chapter, you'll need to download Xcode version 11.4 or above from Apple's App Store.

You'll also need to be running the latest version of macOS (Catalina or above). Simply search for Xcode in the App Store and select and download the latest version. Launch Xcode and follow any additional installation instructions that your system may prompt you with. Once Xcode has fully launched, you're ready to go.

Download the sample code from the following GitHub link: https://github.com/PacktPublishing/Mastering-iOS-14-Programming-4th-Edition.

What is Dark Mode?

In this section, we'll start by taking a look at what exactly Dark Mode is, how we can use it, and what it can do not only for the end user but also for developers. We'll cover everything from enabling it on our devices to using environment overrides in Xcode and developer options in the simulator.

Understanding why we would need Dark Mode

As I covered in the introduction of this chapter, most of us have been craving dark mode in iOS for a very long time now. Us developers got our Xcode fix back in 2018 – but one of the burning questions I've been asked many times (especially in the past 12 months) is…why?

It could be down to something as simple as the time of the day. Satellite navigation systems have been doing it in our cars for years – as soon as the sun goes down, our system switches, and a more relaxing, subtle version of our road home pops up on our screen – so why not do that for our apps?

Well, it turns out that some apps have already been doing that for a while (to a degree), while not necessarily offering an automatic nocturnal mode. The Twitter app for iOS offered a "dark mode" option long before the WWDC 19 announcement.

Let's stop for a moment and think about the logic behind such a control, along with everything you'd need to change to achieve this. I'm sure a company as big as Twitter has written their own internal framework to handle this, but under the hood, it's basically going look a lot like the following:

var isDarkMode = false
var profileLabel: UILabel? {
    didSet {
        profileLabel?.textColor = isDarkMode ? .white : .black
    }
}
var profileBackground: UILabel? {
    didSet {
        profileBackground?.textColor = isDarkMode ? .black : .white
    }
}

Everything will have to be taken into consideration, from the text color to the drop shadows that you might have decorating your UIButton or UIViews.

The background is a massive change to consider too. One common pattern that a lot of iOS developers follow is to quite simply develop a brand-new app on top of a white canvas; from here, we don't need to worry about controlling the background color or keeping track of it with an IBOutlet – it's simply the tablecloth for the rest of our app to sit on.

With implementing a dark mode feature, everything needs to be changed – even asset images that sit proudly on one style of background could be lost in another. Let's take a look at some of the developer features that come bundled with Xcode when implementing Dark Mode.

Core developer concepts of Dark Mode

Let's start by taking a look at how we go about developing with Dark Mode by switching to it on our device. If you've not already done this, you can simply toggle it by going to Settings | Display & Brightness, and you should be presented with the following screen:

Figure 2.1 – Display and brightness

Figure 2.1 – Display and brightness

You'll also notice the Automatic toggle option too, giving us the ability to use either Sunset to Sunrise or a custom schedule, which will automatically switch between light and dark appearance (just like our sat nav).

Now that we've got that covered, let's take a look at some options given to developers in the iOS simulator. Let's start by taking the following steps:

  1. Open up Xcode.
  2. Launch the simulator (Xcode | Open Developer Tool | Simulator).

    In a slightly different location than the end user's version of iOS, you'll find the dark toggle under the developer settings (Settings | Developer | Dark Appearance):

Figure 2.2 – Dark mode developer settings

Figure 2.2 – Dark mode developer settings

Rather than a fancy interface like we saw earlier, we're presented with just the standard toggle. Let's take a look now at what we can do as developers with Dark Mode.

Dark mode from inside Xcode

Now that we've taken a look at how iOS handles switching to dark mode, let's have a look at how we, the developer, can do the same in Xcode.

Out of the box, all new projects building against the iOS 13 SDK will automatically support dark mode; however, building against any earlier SDKs won't.

This helps out a little as your existing app may not have all the necessary tweaks to support dark mode yet and you don't want to release an update to find you have broken your app for those now running dark mode.

However, if you update your project to the iOS 13 SDK, then you could potentially run into this problem, but don't worry, we'll cover getting your existing app ready for dark mode later, in the Migrating existing apps to Dark Mode section in this chapter.

Let's start by having a look at storyboards – we all love them (or hate them) but the one thing they have done over the years is present themselves on a whiter-than-white canvas.

Let's get started:

  1. Launch Xcode and create a new Single View - Storyboard project.
  2. Call this anything you want (I'll call mine Chapter 2 - Dark Mode).

    You can either follow along throughout this chapter or download the sample code from GitHub.

Once created, click on Main.Storyboard and you should be presented with the following:

Figure 2.3 – Xcode interface style

Figure 2.3 – Xcode interface style

I've highlighted in the preceding screenshot our area of interest – here, we have a preview toggle for both light and dark appearances from within the storyboard, so at a quick glance, we can see what the objects we've added to our canvas look like without the need to launch the simulator.

Now, this won't always help us as some of our UILabels or UIButtons could be decorated programmatically. However, it's a great start and will most definitely come in useful during the development cycle of any app.

Let's take a look at our labels in action. Here, we've added a UILabel straight out of the box. Light Appearance is selected, and the label looks just how we are used to seeing things at this stage:

Figure 2.4 – Main storyboard

Figure 2.4 – Main storyboard

Now, let's switch the toggle to Dark Appearance and see what happens:

Figure 2.5 – Main storyboard – dark mode

Figure 2.5 – Main storyboard – dark mode

As if by magic, our canvas enters dark mode, and the color of our UILabel is automatically adjusted. We can see straight away, without the need to compile or run the app on a device or in the simulator, how it will look with each interface style.

I guess the million-dollar question is how did iOS know to switch the color of the UILabel's font? Good question, and we'll cover that in more detail in the Working with views and Dark Mode section later in this chapter.

However, as I mentioned earlier, there are going to be occasions where you'll need to test your app in the simulator. Labels and views will not always be static and could be generated dynamically – this is where environment overrides come in.

We'll start by launching our app in the simulator. Once successfully launched, you should see the following highlighted option available in Xcode:

Figure 2.6 – Environment Overrides

Figure 2.6 – Environment Overrides

Click on this icon and you'll be presented with the Environment Overrides popup. Here, you'll have the option to toggle the Interface Style overrides, which in turn will allow you to choose between light and dark appearance.

If you flick the toggle and switch between each option, you'll see your app in the simulator automatically update without the need to close your app, change the settings, and re-launch. Very nice indeed – thanks, Xcode!

One last little thing to point out before we move on: we mentioned previously that existing apps built with previous iOS SDKs won't be affected by dark mode, but should you choose to update your app to the iOS 13 SDK, you may run into a couple of issues.

Tight deadlines and urgent bug fixes might not necessarily give you the chance to adopt dark mode in your app, so Xcode gives you the option to force light appearance regardless of the user's preference.

In Info.plist (or the Info tab under our project settings), add the following key with the value Light:

UIUserInterfaceStyle
Figure 2.7 – Info.plist – User Interface Style

Figure 2.7 – Info.plist – User Interface Style

You'll now see that even with the environment overrides, you won't be able to switch to dark mode.

In this section, we got up and running with Dark Mode in iOS and, more importantly, Xcode, and learned about the little things that Xcode does to get us ready for developing our apps in both light and dark appearance. In the next section, we'll begin to look at how Xcode handles views and introduce ourselves to semantic "dynamic" colors.

Working with views in Dark Mode

So far in this chapter, we've covered not only what dark mode is but also what it has to offer from a development perspective.

In this chapter, we're going to deep dive further into dark mode by looking at how Xcode dynamically handles our UIViews (and objects that are sub-classed from UIViews).

We'll start by understanding the core concept behind adaptive and semantic colors, and by following a simple pattern, Xcode can do so much of the heavy lifting for us.

We'll then dive further and take a look at the various levels of semantic colors available to us, including primary, secondary, and tertiary options, but more importantly, when we would be expected to use them.

What are adaptive colors?

For me, this was a major step in getting developers on board with designing and developing their apps for dark mode and, of course, it was well within Apple's interest to make it as seamless as possible for the developer.

Adaptive colors are a way of defining a single color type or style for a particular appearance. Let's start by diving straight into Xcode and seeing this for ourselves:

  1. Head back on over to the project you previously created and highlight the UILabel we added in.
  2. Now, take a look at the Color property in the Attributes Inspector window:
Figure 2.8 – Label properties

Figure 2.8 – Label properties

You'll notice that the color selected is Default (Label Color)Label Color is our adaptive color.

But what does that mean? Actually, it's very simple: it means that for one interface style it's one color, and for the other, it's a different color.

In the case of our previous example, our UILabel was black in light mode and white in dark mode – makes sense, right?

Well, to a degree is does, but surely it depends on what type of background our UILabel sits on – let's take a look.

Back in our storyboard, highlight the background of our view and again head over to the Attributes Inspector window:

Figure 2.9 – Background color properties

Figure 2.9 – Background color properties

Again, here we have our adaptive color, System Background Color. Xcode is doing all the work for us when we need to switch appearances.

The preceding parts in the section are a great example of contrasting between two primary colors (black and white used in our labels), which itself is the stereotypical understanding between what colors should be in light and dark appearance – but we're not always going to be using black or white, are we?

So, Apple has updated all their available system colors to be adaptive. Let's take a look.

Head back over to Xcode and highlight our UILabel, and change Color to System Indigo Color:

Figure 2.10 – Font color properties

Figure 2.10 – Font color properties

Now, let's switch between light and dark mode using the toggle in Xcode's storyboard. What do we see? The color indigo, just as we expected:

Figure 2.11 – Light mode with Indigo text color

Figure 2.11 – Light mode with Indigo text color

The following screenshot shows the screen with dark mode:

Figure 2.12 – Dark mode with indigo text color

Figure 2.12 – Dark mode with indigo text color

However, each system color has been specifically adapted to each appearance. Let's take a look at the RGB values for each appearance:

  • Dark: R 94: G 92: B 230
  • Light: R 88: G 86: B 214

Although there is a subtle difference in each RGB value, it has a massive effect in terms of appearance and allowing it to stand out against other adapted colors defined by Apple (such as our system background color).

Now that we've learned all about adaptive colors, let's take a look at semantic colors and how Apple helps us pre-define not only the colors we want to use but also where a type of color should be used.

What are semantic colors?

To answer the questions of this section requires us to take a quick look back at what we already covered in the What are adaptive colors? section, because we've already touched on semantic colors.

Remember Label Color from our UILabel and System Background Color? These are all semantic colors – not so much by physical color, but more by their definition and intended purpose.

With semantic colors, Apple has created a whole pre-defined range of adaptive colors that are designed specifically for objects such as labels, backgrounds, and grouped content such as table views. Each of these has additional primary, secondary, and tertiary variants.

Let's put this into practice and update our current Xcode project:

Figure 2.13 – UILabel with semantic variants

Figure 2.13 – UILabel with semantic variants

I've added a couple more UILabels here and just done a little bit of re-arranging (nothing special), but what I have done is set the semantic variant for each Label with a corresponding variant – let's take a look:

Figure 2.14 – Color options

Figure 2.14 – Color options

If we expand the color options for our UILabel, we can see a list of all the pre-defined adaptive/semantic and system and variant colors available to us. I've highlighted the colors I've chosen for each of the new labels.

Now, let's switch the appearance to dark and see how it looks:

Figure 2.15 – Semantic labels in Dark Mode

Figure 2.15 – Semantic labels in Dark Mode

Let's go a step further and add some more adaptive content in there. Here, I've dropped in a UIView to act as a separator between content, a UIButton, which will be a URL link, and a UITableView:

Figure 2.16 – Separators and other background colors

Figure 2.16 – Separators and other background colors

I've assigned the following semantic colors to each of my new views:

  • Separator: Separator Color
  • Button: Link Color
  • Table View: Group Table View Background Color

Let's fire this up in the iOS simulator and see side by side how it looks. You'll notice something interesting:

Figure 2.17 – Table view in light and Dark Mode

Figure 2.17 – Table view in light and Dark Mode

In the light appearance, you can clearly see the table view's group background color against the system background color; yet if we take a look at this in the dark appearance, you don't see it as much. That's because with a much darker primary background color, the separation isn't needed as much; the black on black doesn't get lost and looks more natural, whereas white on white does.

This all looks great built into Interface Builder, but now let's take a look at how we would do this programmatically.

Using the programmatic approach

Let's start by creating IBOutlets for each of our objects. If you're unfamiliar with creating an outlet, simply, in ViewController, we do the following:

  1. Declare all our outlet properties first.
  2. Then, from the IBOutlet connector (just to the left of your property), press Command + Primary Cursor Click.
  3. Hold and drag this to the UIView or object you want to connect to.

    Opening both Interface Builder and ViewController in separate windows will really help this process too:

    Figure 2.18 – Creating an outlet

    Figure 2.18 – Creating an outlet

  4. We'll need to create these in our ViewController.swift file just inside the class declaration. Copy the following highlighted code into your class:
    class ViewController: UIViewController {
        @IBOutlet weak var headerImageView: UIImageView!
        @IBOutlet weak var primaryLabel: UILabel!
        @IBOutlet weak var secondaryLabel: UILabel!
        @IBOutlet weak var tertiaryLabel: UILabel!
        
        @IBOutlet weak var linkButton: UIButton!
        
        @IBOutlet weak var separatorView: UIView!
        
        @IBOutlet weak var tableView: UITableView!
        
        
        override func viewDidLoad() {
            super.viewDidLoad()
        }
    }
  5. Now, we can programmatically assign our colors. Inside the viewDidLoad() function, add the following highlighted code:
    override func viewDidLoad() {
        super.viewDidLoad()
            
        primaryLabel.textColor = UIColor.label
        secondaryLabel.textColor = UIColor.secondaryLabel
        tertiaryLabel.textColor = UIColor.tertiaryLabel
            
        linkButton.titleLabel?.textColor = UIColor.link
            
        separatorView.backgroundColor = UIColor.separator
            
        tableView.backgroundColor = UIColor.systemGroupedBackground
            
    }

If you launch the app in the simulator, you'll see that everything should stay the same. If we really want to test our logic, head back on over to Interface Builder and set one of our UILabels to System Green Color. Re-run the app and watch the programmatic code take precedence and override Interface Builder.

In this section, we've looked at how working with views for Dark Mode either in Interface Builder or programmatically is possible with the use of adaptive and semantic colors. We also looked at and understood the value behind using color variations and saw the effect they both have in both light and dark appearance. In the next section, we'll take a look at the asset catalog and how we can create custom adaptive colors and images for use in our app.

Working with the asset catalog for Dark Mode

Since the ability to add colors to the asset catalog became available back in Xcode 9, there is now even more reason to take full advantage of one of Xcode's prized assets.

In this section, we'll look at how we can use the asset catalog not only to create our custom colors but also to create our own adaptive colors and images, allowing us to harness the power of Xcode when developing dynamic appearance applications.

Using custom adaptive colors

Sticking with our current project, head on over to the file inspector, and highlight the Assets.xcassets folder. With the following layout visible, click on the + button highlighted in the following screenshot and select New Color Set from the list of options:

Figure 2.19 – Creating a color set

Figure 2.19 – Creating a color set

Add in another three color sets and name them the following:

  • brandLabel
  • brandSecondaryLabel
  • brandTertiaryLabel

Highlight brandLabel, and then highlight the option in the central asset preview window. Notice the list of attribute options now made available to us in the Attributes Inspector pane:

Figure 2.20 – Adding a color set

Figure 2.20 – Adding a color set

As you can see, we can now define the brandLabel color that we want to use. But first, let's make it adaptive. In the Attributes Inspector pane, change Appearance from None to Any, Light, Dark.

You'll have noticed on the dropdown that there was another option of Any, Dark, so let's go through what this means:

  • None: This is a default color and won't be adaptive to your selected appearance.
  • Any, Dark: In this scenario, Any will support legacy versions of your app, along with any other variations that aren't dark (so light, basically). Dark will be dark…
  • Any, Light, Dark: Same as the preceding but will allow you to specifically select a value for legacy and light (along with dark).

So, with that covered, let's add some colors. Now, as mentioned before, this is where you can be really specific with your color choices, either by personal preference or brand guidelines you have to follow. For me, I'm just going to click Show Color Picker and pick my favorite colors:

  • Tangerine for Any (Legacy) and light
  • A more subtle Cantaloupe for dark:
Figure 2.21 – Choosing a color

Figure 2.21 – Choosing a color

Do the same for brandSecondaryLabel and brandTertiaryLabel, remembering to slightly alter the colors based on the semantic purpose you intend to use them for.

Once you've done that, head back on over to Interface Builder and highlight primaryLabel, then bring open the options of colors from Attributes Inspector. You should see the following:

Figure 2.22 – Default label color

Figure 2.22 – Default label color

All the color sets you created in the asset catalog are available to use right there in Interface Builder. Go ahead and add them in for each label and see how they look by switching appearance in Interface Builder:

Figure 2.23 – Color set, light mode versus dark mode

Figure 2.23 – Color set, light mode versus dark mode

With that done, you've created your very own adaptive, semantic and dynamic colors for your app – all within the power of Xcode.

If you wanted to use the colors programmatically, you can do that by simply referring to the asset name in a couple of different ways.

First is a direct reference to the name of the assets:

primaryLabel.textColor = UIColor(named: "brandLabel")

Alternatively, you can select the asset directly from the media library by pressing Shift + CMD + M and selecting show color palette from the icon options and selecting the color you want.

This will insert the color from the assets catalog as a swatch, directly inside your code:

Figure 2.24 – Assigning a color set programmatically

Figure 2.24 – Assigning a color set programmatically

Or another option, if you really wanted to keep your code clean, would be to create an extension of UIColor allowing you to define your own property:

extension UIColor {
    static var brandLabel: UIColor {
        return UIColor(named: "brandLabel") ?? UIColor.label
    }
}

This can now be used just like this:

primaryLabel.textColor = UIColor.brandLabel

This is a nice, clean, and manageable way to look after your custom color sets programmatically, but this really is a personal preference, and each to their own. If you're working with a large alternative color guideline, making the change to a primary color in one extension will roll the change out to your entire app without the worry of missing a label or two.

Next, let's take a look at the same approach but for images.

Using custom adaptive images

We've learned a lot about how the asset catalog works with adaptive images from the previous section, Custom adaptive colors, and luckily, we can take full advantage of that in creating adaptive images for our project.

In the same way that we created a new color set, let's follow these steps:

  1. Head on back over to Assets.xcassets.
  2. Create a new image set:
    Figure 2.25 – New image set

    Figure 2.25 – New image set

  3. Name your new image header, highlight it, and change the appearance in the Attributes Inspector window to Any, Dark. You should now see the following:
Figure 2.26 – Add new image set

Figure 2.26 – Add new image set

When adding an image to the image catalog, you'll be given the option for adding 1x, 2x, or 3x images – these are different image scales you can set for various screen sizes. For further information, see the following from Apple's documentation.

For this example, we are going to add in two different images to the 2x option: one for Any and the other for Dark. You can grab the images I've used from the sample project found in GitHub or choose your own – it's up to you. From the Finder, simply drag and drop the images into the 2x placeholder inside Xcode. You should see the following once done:

Figure 2.27 – New image set variants

Figure 2.27 – New image set variants

Now, head back on over to your storyboard and add in a UIImageView to your project. Add this to the top of ViewController to act as a header.

Once in place, head on over to the Attributes Inspector pane and select the dropdown for the Image option – there, you should see your newly created asset, header:

Figure 2.28 – Setting header from the image set

Figure 2.28 – Setting header from the image set

Select this and take a look (depending on the size of the image you chose, you may need to set Content Mode to Aspect Fill – these options can also be found in Attributes Inspector).

Run the simulator and have a look at everything you've achieved so far in this chapter, remembering to switch from light to dark appearance by using the environment override in Xcode… looks pretty good, right?

Figure 2.29 – Header light mode versus dark mode

Figure 2.29 – Header light mode versus dark mode

Just like we did with color sets, we can of course handle this programmatically, should we wish. Let's add another extension to our app to handle this for us:

extension UIImage {
    static var header: UIImage {
        return UIImage(named: "header") ?? UIImage()
    }
}

We can again use this in just the same way as before:

headerImageView.image = UIImage.header

We do this by assigning our header image directly onto our UIImageView.

In this section, we harnessed the power of the asset catalog to allow us to create custom adaptive and dynamic colors and images for our app. In the next section, we'll take a look at how best to update a legacy app to support dark mode with everything we've learned so far, and also how best to identify the little things we can do to futureproof our apps for various appearances.

Further exploring Dark Mode

In the previous sections, we gave you a lot to think about when either creating or migrating existing apps to Dark Mode under specific circumstances. In this section, we'll take a look at a couple of little "nice to knows" that should always be in the back of your mind when approaching Dark Mode.

Using Dark Mode with SwiftUI

With the announcement of SwiftUI back in June 2019, a massive shift in focus on UI-based development took place. Released at the same time as Dark Mode, and as expected, SwiftUI takes full advantage of switching appearances.

Let's start by taking a look at how we could detect dark mode programmatically in SwiftUI:

  1. First, we'll create an environment variable that allows us to access the current state of the appearance of the device:
    @Environment(\.colorScheme) var appearance
  2. Next, let's use a simple ternary operator to display some text based on the current appearance:
    Text(appearance == .dark ? "Dark Appearance" : "Light Appearance")

It really is that simple.

Now, let's have a look at the options available to us in the automatic preview window. SwiftUI uses PreviewProvider, which allows us to display dynamically what we are designing/developing.

To enable Dark Mode in PreviewProvider, simply add the following highlighted code and hot refresh:

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .environment(\.colorScheme, .dark)
    }
}

Here, we've added a modifier to set the .colorScheme environment variable to .dark. If we want to preview both .light and .dark side by side, we can simply do the following:

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            ContentView().environment(\.colorScheme, .light)
             ContentView().environment(\.colorScheme, .dark)
        }
    }
}

Tip

To learn more about SwiftUI, take a look at Learn SwiftUI, available from Packt Publishing: https://www.packtpub.com/business-other/learn-swiftui.

Programatically handling changes with trait collection

During the development of your new app, there could be a couple of occasions where you might need to handle a specific scenario based on the current appearance. However, we'll need to take a slightly different approach to this than what we did with the SwiftUI example previously.

The interface style is part of the UITraitCollection class (which, in turn, is part of UIKit). We can do a conditional check against a value using the following anywhere in our ViewController:

traitCollection.userInterfaceStyle == .dark

Unlike SwiftUI, we can't just use a simple ternary operator as there are more than two values for userInterfaceStyle:

public enum UIUserInterfaceStyle : Int {
    case unspecified
    case light
    case dark
}

Unspecified is an option too (think Any, back in our asset catalog), so it's best to use another approach when detecting changes to our interface style.

Let's start by heading back into our ViewController.swift file and adding in the following override function:

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    // Logic here    
}

This override is called whenever a change is made to a trait (such as appearance). From this, we now action any changes we would like to make, but the problem we have is traits are used for more than just appearances, and this override could be called for a variety of reasons.

So, if we are looking particularly for changes in our appearance, we can use the previousTrait property passed into our delegate function and compare against the current system trait – if there is a difference, we know the appearance has changed. Let's take a look at how we'd do this:

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    let interfaceAppearanceChanged = previousTraitCollection?.hasDifferentColorAppearance(comparedTo: traitCollection)
}

By using the hasDifferentColorAppearance method, we can now easily compare the previous trains against the current one to see whether there have been any changes – the resulting method returns a Boolean, so we can use this at our convenience.

Specifying an appearance for views, ViewControllers, and windows

You may, in some circumstances, wish to specify an appearance based on a particular area of your app or if you are migrating to dark mode (but need a little more time for a certain feature). Simply drop in the following appropriate code to meet your desire.

Views

Here, we'll create and instantiate a basic UIView:

let view = UIView()
view.overrideUserInterfaceStyle = .dark // .light

We assign either a light or dark value.

ViewController

If we wanted to do this in a UIViewController, we would simply just do the following:

overrideUserInterfaceStyle = .dark

Again, we assign either a light or dark value (usually within viewDidLoad()).

Window

If we need to access the current window, we could do so as follows:

for window in UIApplication.shared.windows {
    window.overrideUserInterfaceStyle = .dark
}

(This is not a recommended approach and you would be hard-pressed to find any real reason to want to do this…)

Accessibility in Dark Mode

Ask around and someone will joke about how Dark Mode has existed in iOS for years, either as the Classic Invert or Smart Invert accessibility feature. I even had it on one of my slides at a conference about 2 months prior to Dark Mode being officially announced.

But with this in mind, a lot of things started to be said about accessibility in iOS – some comments referring to Dark Mode as "Apple finally supporting accessibility," which I have to be honest makes me very sad.

Accessibility has always played a massive part in iOS regardless of the appearance – but, even with the introduction of Dark Mode, this still goes unchanged as Dark Mode supports all accessibility features.

If you refer back to an earlier section in this chapter, Core development concepts in Dark Mode, you'll remember that we mentioned the option to schedule our light and dark appearances – much like you could with Nightshift that was introduced in iOS 9, again another element with a focus on accessibility.

In this section, we went a little outside of the box with regard to Dark Mode and stepped away from the basic implementation, allowing us to look at the wider options available to use and things to think about when implementing Dark Mode in our apps.

Summary

In this chapter, we've covered a lot about Dark Mode – not only from a programmatic perspective but also the theory behind the appearances and purpose of colors used within our apps.

We started by taking a look at how Xcode and iOS are set up for Dark Mode, learning about the environment overrides used in Xcode, and how we can even switch appearances in our storyboard while developing.

Next, we covered adaptive and semantic colors, and learned not only how these are used with Apple's default system colors but also how we can create dynamic and adaptive color sets ourselves.

Following on from what we learned about color sets, we applied this to images and harnesses the power of the assets catalog.

Finally, we covered some "great to know" topics, such as Dark Mode in SwiftUI, programmatically hailing appearances, and accessibility.

In the next chapter, we'll take a look at lists in iOS 14, covering everything you need to know about UITableViews and UICollectionViews.

Left arrow icon Right arrow icon
Download code icon Download Code

Key benefits

  • Explore the world of iOS app development through practical examples
  • Understand core iOS programming concepts such as Core Data, networking, and the Combine framework
  • Extend your iOS apps by adding augmented reality and machine learning capabilities, widgets, App Clips, Dark Mode, and animations

Description

Mastering iOS 14 development isn’t a straightforward task, but this book can help you do just that. With the help of Swift 5.3, you’ll not only learn how to program for iOS 14 but also be able to write efficient, readable, and maintainable Swift code that reflects industry best practices. This updated fourth edition of the iOS 14 book will help you to build apps and get to grips with real-world app development flow. You’ll find detailed background information and practical examples that will help you get hands-on with using iOS 14's new features. The book also contains examples that highlight the language changes in Swift 5.3. As you advance through the chapters, you'll see how to apply Dark Mode to your app, understand lists and tables, and use animations effectively. You’ll then create your code using generics, protocols, and extensions and focus on using Core Data, before progressing to perform network calls and update your storage and UI with the help of sample projects. Toward the end, you'll make your apps smarter using machine learning, streamline the flow of your code with the Combine framework, and amaze users by using Vision framework and ARKit 4.0 features. By the end of this iOS development book, you’ll be able to build apps that harness advanced techniques and make the best use of iOS 14’s features.

Who is this book for?

This book is for developers with some experience in iOS programming who want to enhance their application development skills by unlocking the full potential of the latest iOS version with Swift.

What you will learn

  • Build a professional iOS application using Xcode 12.4 and Swift 5.3
  • Create impressive new widgets for your apps with iOS 14
  • Extend the audience of your app by creating an App Clip
  • Improve the flow of your code with the Combine framework
  • Enhance your app by using Core Location
  • Integrate Core Data to persist information in your app
  • Train and use machine learning models with Core ML
  • Create engaging augmented reality experiences with ARKit 4 and the Vision framework
Estimated delivery fee Deliver to Greece

Premium delivery 7 - 10 business days

€17.95
(Includes tracking information)

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : Mar 19, 2021
Length: 558 pages
Edition : 4th
Language : English
ISBN-13 : 9781838822842
Vendor :
Apple
Category :
Languages :
Tools :

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Product feature icon AI Assistant (beta) to help accelerate your learning
Estimated delivery fee Deliver to Greece

Premium delivery 7 - 10 business days

€17.95
(Includes tracking information)

Product Details

Publication date : Mar 19, 2021
Length: 558 pages
Edition : 4th
Language : English
ISBN-13 : 9781838822842
Vendor :
Apple
Category :
Languages :
Tools :

Packt Subscriptions

See our plans and pricing
Modal Close icon
€18.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
€189.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts
€264.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts

Frequently bought together


Stars icon
Total 115.97
Mastering iOS 14 Programming
€41.99
Swift Cookbook
€41.99
SwiftUI Cookbook
€31.99
Total 115.97 Stars icon

Table of Contents

21 Chapters
Chapter 1: What's New in iOS 14? Chevron down icon Chevron up icon
Chapter 2: Working with Dark Mode Chevron down icon Chevron up icon
Chapter 3: Using Lists and Tables Chevron down icon Chevron up icon
Chapter 4: Creating a Detail Page Chevron down icon Chevron up icon
Chapter 5: Immersing Your Users with Animation Chevron down icon Chevron up icon
Chapter 6: Understanding the Swift Type System Chevron down icon Chevron up icon
Chapter 7: Flexible Code with Protocols, Generics, and Extensions Chevron down icon Chevron up icon
Chapter 8: Adding Core Data to Your App Chevron down icon Chevron up icon
Chapter 9: Fetching and Displaying Data from the Network Chevron down icon Chevron up icon
Chapter 10: Making Smarter Apps with Core ML Chevron down icon Chevron up icon
Chapter 11: Adding Media to Your App Chevron down icon Chevron up icon
Chapter 12: Improving Apps with Location Services Chevron down icon Chevron up icon
Chapter 13: Working with the Combine Framework Chevron down icon Chevron up icon
Chapter 14: Creating an App Clip for Your App Chevron down icon Chevron up icon
Chapter 15: Recognition with Vision Framework Chevron down icon Chevron up icon
Chapter 16: Creating Your First Widget Chevron down icon Chevron up icon
Chapter 17: Using Augmented Reality Chevron down icon Chevron up icon
Chapter 18: Creating a macOS app with Catalyst Chevron down icon Chevron up icon
Chapter 19: Ensuring App Quality with Tests Chevron down icon Chevron up icon
Chapter 20: Submitting Your App to the App Store Chevron down icon Chevron up icon
Other Books You May Enjoy Chevron down icon Chevron up icon

Customer reviews

Top Reviews
Rating distribution
Full star icon Full star icon Full star icon Full star icon Half star icon 4.7
(15 Ratings)
5 star 93.3%
4 star 0%
3 star 0%
2 star 0%
1 star 6.7%
Filter icon Filter
Top Reviews

Filter reviews by




Balazs A Mar 29, 2021
Full star icon Full star icon Full star icon Full star icon Full star icon 5
It's the deepest book on iOS development I have ever purchased on Amazon.
Amazon Verified review Amazon
zoha Apr 12, 2021
Full star icon Full star icon Full star icon Full star icon Full star icon 5
If you're looking to make an iOS app, and you want to learn how to do it properly this is the book with the perfect foundation. It starts with an intro on what's new in IOS 14 and goes over all the advanced and latest concepts like the widgetkit, ARkit, Machine learning, etc in a step-by-step detailed manner. it really spoke to me in a way that was easy to understand.
Amazon Verified review Amazon
Jean Meyer (iOS Dev & Crypto Guru) Mar 30, 2021
Full star icon Full star icon Full star icon Full star icon Full star icon 5
I really believed I knew how to dev on iOS... Well, I didn't. This book isn't reinventing the wheel. It explains in detail every iOS concept. Perfect fit both for beginners and pros as it will take your hand step by step from the "Idea stage" to "Publishing your app to the AppStore"... Congrats to the authors. I would have maybe appreciated a chapter about iOS & Blockchain but I guess that will come in the next edition ;)
Amazon Verified review Amazon
jared cassoutt Mar 22, 2021
Full star icon Full star icon Full star icon Full star icon Full star icon 5
I love this book! Not only does it cover many of the topics that are necessary to be an iOS developer, but it also includes many fun topics such as CoreML, ARKit 4, and the Vision Framework. I would highly recommend this book to any current mobile developers or individuals looking to become an iOS developer!!!
Amazon Verified review Amazon
Gurleen Kaur May 21, 2021
Full star icon Full star icon Full star icon Full star icon Full star icon 5
Most of the concepts are explained very well and it is really interesting to keep reading.As a iOS developer, who is getting back into development it’s really great to revise the concept and everything new in the update.I really love the book and highly recommend it
Amazon Verified review Amazon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

What is the delivery time and cost of print book? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela
What is custom duty/charge? Chevron down icon Chevron up icon

Customs duty are charges levied on goods when they cross international borders. It is a tax that is imposed on imported goods. These duties are charged by special authorities and bodies created by local governments and are meant to protect local industries, economies, and businesses.

Do I have to pay customs charges for the print book order? Chevron down icon Chevron up icon

The orders shipped to the countries that are listed under EU27 will not bear custom charges. They are paid by Packt as part of the order.

List of EU27 countries: www.gov.uk/eu-eea:

A custom duty or localized taxes may be applicable on the shipment and would be charged by the recipient country outside of the EU27 which should be paid by the customer and these duties are not included in the shipping charges been charged on the order.

How do I know my custom duty charges? Chevron down icon Chevron up icon

The amount of duty payable varies greatly depending on the imported goods, the country of origin and several other factors like the total invoice amount or dimensions like weight, and other such criteria applicable in your country.

For example:

  • If you live in Mexico, and the declared value of your ordered items is over $ 50, for you to receive a package, you will have to pay additional import tax of 19% which will be $ 9.50 to the courier service.
  • Whereas if you live in Turkey, and the declared value of your ordered items is over € 22, for you to receive a package, you will have to pay additional import tax of 18% which will be € 3.96 to the courier service.
How can I cancel my order? Chevron down icon Chevron up icon

Cancellation Policy for Published Printed Books:

You can cancel any order within 1 hour of placing the order. Simply contact customercare@packt.com with your order details or payment transaction id. If your order has already started the shipment process, we will do our best to stop it. However, if it is already on the way to you then when you receive it, you can contact us at customercare@packt.com using the returns and refund process.

Please understand that Packt Publishing cannot provide refunds or cancel any order except for the cases described in our Return Policy (i.e. Packt Publishing agrees to replace your printed book because it arrives damaged or material defect in book), Packt Publishing will not accept returns.

What is your returns and refunds policy? Chevron down icon Chevron up icon

Return Policy:

We want you to be happy with your purchase from Packtpub.com. We will not hassle you with returning print books to us. If the print book you receive from us is incorrect, damaged, doesn't work or is unacceptably late, please contact Customer Relations Team on customercare@packt.com with the order number and issue details as explained below:

  1. If you ordered (eBook, Video or Print Book) incorrectly or accidentally, please contact Customer Relations Team on customercare@packt.com within one hour of placing the order and we will replace/refund you the item cost.
  2. Sadly, if your eBook or Video file is faulty or a fault occurs during the eBook or Video being made available to you, i.e. during download then you should contact Customer Relations Team within 14 days of purchase on customercare@packt.com who will be able to resolve this issue for you.
  3. You will have a choice of replacement or refund of the problem items.(damaged, defective or incorrect)
  4. Once Customer Care Team confirms that you will be refunded, you should receive the refund within 10 to 12 working days.
  5. If you are only requesting a refund of one book from a multiple order, then we will refund you the appropriate single item.
  6. Where the items were shipped under a free shipping offer, there will be no shipping costs to refund.

On the off chance your printed book arrives damaged, with book material defect, contact our Customer Relation Team on customercare@packt.com within 14 days of receipt of the book with appropriate evidence of damage and we will work with you to secure a replacement copy, if necessary. Please note that each printed book you order from us is individually made by Packt's professional book-printing partner which is on a print-on-demand basis.

What tax is charged? Chevron down icon Chevron up icon

Currently, no tax is charged on the purchase of any print book (subject to change based on the laws and regulations). A localized VAT fee is charged only to our European and UK customers on eBooks, Video and subscriptions that they buy. GST is charged to Indian customers for eBooks and video purchases.

What payment methods can I use? Chevron down icon Chevron up icon

You can pay with the following card types:

  1. Visa Debit
  2. Visa Credit
  3. MasterCard
  4. PayPal
What is the delivery time and cost of print books? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela