Updating Your View for Dark Mode in SwiftUI

Dark.gif

I don’t know about you, but I use dark mode on everything. Well, everything that supports it at least! And by the end of this post you’ll have everything you need to update your SwiftUI views to support dark mode.

The @Environment Property Wrapper

Along with the @State property wrapper, SwiftUI also has a property wrapper called @Environment. With Environment you can access system settings such as accessibility controls, dynamic type adjustments like line spacing, and the current horizontal and vertical size classes from any SwiftUI view. You can also access the current ColorScheme, which is exactly what we need to check to know if the app is in dark or light mode.

@Environment(\.colorScheme) var colorScheme

It’s as easy as adding a property that is marked with the @Environment property wrapper, telling it which Environment value to use. You can find a list of all the available Environment values in Apple’s documentation here.

ColorScheme, the Environment value we’re using here, is an enum with two cases:

  • .light

  • .dark

So knowing that we can use it just like any other enum to change how our view is displayed. For example, here is how the text in the gif above is updated:

Text(colorScheme == .dark ? "Dark Mode" : "Light Mode")

Now whenever the user updates their system setting for dark mode the view observes that change and updates the text to match. Super easy!

Umm… but why isn’t my preview updating?

If you’re using the Preview Canvas in Xcode then you probably noticed that there’s no way in the preview itself to switch to dark mode and back. Luckily we can pass in specific Environment values to test things in different real world scenarios. Just add the .environment modifier to your view in the previews code at the bottom and you’re all set!

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

And here’s the full code for the example in the gif at the top of this post:

import SwiftUI

struct ContentView: View {
    @Environment(\.colorScheme) var colorScheme

    var body: some View {
        RoundedRectangle(cornerRadius: 20)
            .frame(width: 250, height: 250)
            .foregroundColor(colorScheme == .dark ? .black : .yellow)
            .overlay(
                Text(colorScheme == .dark ? "Dark Mode" : "Light Mode")
                    .font(.title)
                    .foregroundColor(colorScheme == .dark ? .white : .black)
            )
    }
}

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

Creating a Segmented Control in SwiftUI

Next
Next

Creating a Repeating Animation in SwiftUI