How to change status bar color in SwiftUI & SwiftUI 4

DevTechie Inc
Dec 7, 2022


Photo by Onur Binay on Unsplash

iOS provides two color schemes, i.e. light or dark mode, for views and views along with status bar adopts to this color scheme. SwiftUI provides two view modifiers to control these themes.

In this article, we will explore preferredColorScheme and toolbarColorScheme modifiers. toolbarColorScheme was introduced in iOS 16 and is available for SwiftUI 4 and above.

Preferred Color Scheme
preferredColorScheme modifier gives us option to configure light or dark mode for views.

Let’s work on an example to understand this better. We will use following code to create an example view:

struct DevTechieCourse: Identifiable {
    let id = UUID()
    let name: String
    let desc: String
}extension DevTechieCourse {
    static var sampleData: [DevTechieCourse] {
        [
            .init(name: "Maps in SwiftUI using MapKit", desc: "In this video course, we will look at maps in SwiftUI. Goal of the course is to learn all there is about Maps in SwiftUI but also to port over advanced map functionality from UIKit's MapKit. We will build various examples to show the use-case of maps, limitations and capabilities."),
            .init(name: "Photo Gallery App in SwiftUI 4, iOS 16 & PhotosPicker", desc: "In this course you will learn to build real world example of SwiftUI 4. We will build app called PhotosGallary where we will build a SwiftUI app from scratch in SwiftUI 4. You will also learn to use newly introduced photos picker control which is now available as a natively supported component in SwiftUI, starting iOS 16 and SwiftUI4. "),
            .init(name: "What's in in SwiftUI 4: Learn by Building 15 Examples", desc: "n this course we will look at all the major features announced at WWDC22 for SwiftUI 4."),
            .init(name: "Complete E-Commerce App in SwiftUI 3, iOS 15 and Apple Pay", desc: "In this course, we will build E-Commerce app from start to finish using SwiftUI 3 and iOS 15. We will also integrate Apple Pay to allow users to purchase items from the app and let Apple take care of the payment processing. "),
            .init(name: "Food Recipes App in SwiftUI 3 & iOS 15 with Lottie Animation", desc: "In this video course we will build food recipes app using SwiftUI 3 and iOS 15. We will learn about SwiftUI, Generic based JSON decoding, Lottie Animation while building out this app. You will also learn to break views down into smaller subviews to learn about the support of view composition in SwiftUI. We will be building search bar functionality from scratch while using several newly introduced APIs in iOS 15."),
            .init(name: "Build Strava Clone in iOS using MapKit, Realm and UIKit", desc: "In this course we will build a mini Strava clone from scratch. This app will allow you to track user's location using core location along with displaying their location inside a map. You will be building custom controls from scratch while learning about various reusable components. You will learn to build components in code. We will use UIKit, Realm and MapKit to build this app."),
            .init(name: "Top Destinations App in SwiftUI w/ Maps & Lottie Animation", desc: "In this video course, you will learn to build out Top Destinations app from start to finish. This course will cover Hero animation by building matchedAnimation like feature from scratch. You will learn to integrate MapKit into SwiftUI apps. You will learn to parse JSON file using generics along with mapping of custom keys to swift objects using CodingKey enumeration.")
        ]
    }
}struct ContentView: View {
    @State private var courses = DevTechieCourse.sampleData
    
    var body: some View {
        NavigationStack {
            List(courses) { course in
                VStack(alignment: .leading) {
                    Text(course.name)
                        .font(.title)
                        .foregroundColor(.primary)
                    
                    Text(course.desc)
                        .font(.body)
                        .foregroundColor(.secondary)
                }
                .listRowBackground(Color.orange)
            }
            .background(.orange)
            .scrollContentBackground(.hidden)
            .navigationTitle("DevTechie Courses")
        }
    }
}
Build and run:

Note: by pressing cmd+shift+A on simulator, you can toggle between light and dark mode.
As you can see, we have both dark mode and light mode supported for the app. Due to the color choices I have made for app’s UI, for this sample app light mode works better so let’s add preferredColorScheme modifier with value as light.

struct ContentView: View {
    @State private var courses = DevTechieCourse.sampleData
    
    var body: some View {
        NavigationStack {
            List(courses) { course in
                VStack(alignment: .leading) {
                    Text(course.name)
                        .font(.title)
                        .foregroundColor(.primary)
                    
                    Text(course.desc)
                        .font(.body)
                        .foregroundColor(.secondary)
                }
                .listRowBackground(Color.orange)
            }
            .background(.orange)
            .scrollContentBackground(.hidden)
            .navigationTitle("DevTechie Courses")
            .preferredColorScheme(.light)
        }
    }
}
As you can see, despite toggling between light/dark mode, our UI stays in light mode.

Note that preferredColorScheme applies color scheme to its own view hierarchy, this means if we had a page with two different view hierarchies and if the color scheme is applied at the page level, it wouldn’t affect the other page.

Let’s understand this with an example. We will modify our view to have two have two buttons, which will launch two different views.

struct ContentView: View {
    @State private var showCourseHome = false
    @State private var showDevTechieMessage = false
    
    var body: some View {
        VStack {
            Button {
                showCourseHome.toggle()
            } label: {
                Text("Show DevTechie Courses")
            }
            .sheet(isPresented: $showCourseHome) {
                CourseHomeView()
            }
            
            
            Button {
                showDevTechieMessage.toggle()
            } label: {
                Text("Show DevTechie Message")
            }
            .sheet(isPresented: $showDevTechieMessage) {
                Text("Please checkout DevTechie.com for more content and support!!!")
                    .font(.largeTitle)
            }
        }.buttonStyle(.borderedProminent)
    }
}struct CourseHomeView: View {
    @State private var courses = DevTechieCourse.sampleData
    
    var body: some View {
        NavigationStack {
            VStack {
                List(courses) { course in
                    VStack(alignment: .leading) {
                        Text(course.name)
                            .font(.title)
                            .foregroundColor(.primary)
                        
                        Text(course.desc)
                            .font(.body)
                            .foregroundColor(.secondary)
                    }
                    .listRowBackground(Color.orange)
                }
                .background(.orange)
                .scrollContentBackground(.hidden)
                .navigationTitle("DevTechie Courses")
                .preferredColorScheme(.light)
            }
        }
    }
}
Notice that our DevTechieCourses view stays in light theme but DevTechieMessage view adopts system scheme.

If we want to keep theme consistent for entire app, then we will apply preferredColorScheme modifier in the app file as shown below:

@main
struct SwiftUI4PreviewApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .preferredColorScheme(.light)
        }
    }
}
Build and run:


Notice that despite switching scheme, our app keeps the light mode.


toolbarColorScheme
Starting iOS 16 and SwiftUI 4, we can set toolbar color scheme with the help of newly introduced toolbarColorSchememodifier.

Let’s say that we want to set navigation bar for our course list view as dark theme, we can do that as shown below:

struct CourseHomeView: View {
    @State private var courses = DevTechieCourse.sampleData
    
    var body: some View {
        NavigationStack {
            VStack {
                List(courses) { course in
                    VStack(alignment: .leading) {
                        Text(course.name)
                            .font(.title)
                            .foregroundColor(.primary)
                        
                        Text(course.desc)
                            .font(.body)
                            .foregroundColor(.secondary)
                    }
                    .listRowBackground(Color.orange)
                }
                .background(.orange)
                .scrollContentBackground(.hidden)
                .navigationTitle("DevTechie Courses")
                .toolbarColorScheme(.dark, for: .navigationBar)
            }
        }
    }
}
Build and run:

With that we have reached the end of this article. Thank you once again for reading. Don’t forget to follow 😍. Also subscribe our newsletter at https://www.devtechie.com