Hierarchical background styles in SwiftUI

Before iOS 17 to get hierarchical system background colors in SwiftUI we usually had to convert them from UIColor. For example, to get the secondary system background we would write the following code: Color(uiColor: .secondarySystemBackground).

Starting from iOS 17 we now have new properties, such as secondary, tertiary, quaternary and quinary that are defined on an instance of a ShapeStyle. To get hierarchical background colors we simply have to access these properties on the current background style: BackgroundStyle().secondary. BackgroundStyle in SwiftUI conforms to ShapeStyle protocol, so accessing the secondary property on an instance of a BackgroundStyle will return the second level of the background in the current context that depends on the operating system and color scheme (light or dark mode enabled).

We can also get the current background style from the static background property defined on ShapeStyle.

We can see that if we put both the old and the new ways to get hierarchical system background colors side by side, they will be the same. UIKit system background colors go up to the tertiary one.

HStack {
    Image(systemName: "cat")
        .padding()
        .background(Color(uiColor: .secondarySystemBackground))
    
    Image(systemName: "cat")
        .padding()
        .background(.background.secondary)
}

...

Screenshot showing an image of a cat with secondary system background Screenshot showing an image of a cat with secondary system background

Unfortunately, the new instance properties are only available on iOS 17, so if you are supporting older OS versions, you would need to wrap their use in if #available(iOS 17.0, *) and fallback to the previous method for older targets.

if #available(iOS 17.0, *) {
    Image(systemName: "cat")
        .padding()
        .background(.background.secondary)
} else {
    Image(systemName: "cat")
        .padding()
        .background(Color(uiColor: .secondarySystemBackground))
}

Note, that the new instance properties for getting hierarchical shape styles that return some ShapeStyle are different from the static properties available on older iOS versions, such as primary, secondary, tertiary, quaternary and quinary that return HierarchicalShapeStyle. The new instance properties provide a hierarchical level of the shape style that they are accessed on, for example a hierarchical level of the current background style. The static properties always provide a hierarchical level of the current foreground style.

Swift Gems by Natalia Panferova book coverSwift Gems by Natalia Panferova book cover

Level up your Swift skills!$35

100+ tips to take your Swift code to the next level

Swift Gemsby Natalia Panferova

  • Advanced Swift techniques for experienced developers bypassing basic tutorials
  • Curated, actionable tips ready for immediate integration into any Swift project
  • Strategies to improve code quality, structure, and performance across all platforms

Level up your Swift skills!

100+ tips to take your Swift code to the next level

Swift Gems by Natalia Panferova book coverSwift Gems by Natalia Panferova book cover

Swift Gems

by Natalia Panferova

$35

The new instance properties can be accessed on other shape styles too, not just the background style. For example, we can get hierarchical levels of a TintShapeStyle or any SwiftUI Color.

Image(systemName: "cat")
    .padding()
    .background(.tint.secondary)

...


Image(systemName: "cat")
    .padding()
    .background(.green.tertiary)
Screenshot showing levels of the blue tint color and green color Screenshot showing levels of the blue tint color and green color


If you have older iOS apps and want to enhance them with modern SwiftUI features, check out my book Integrating SwiftUI into UIKit Apps. It provides detailed guidance on gradually adopting SwiftUI in your UIKit projects. Additionally, if you're eager to enhance your Swift programming skills, my latest book Swift Gems offers over a hundred advanced tips and techniques, including optimizing collections, handling strings, mastering asynchronous programming, and debugging, to take your Swift code to the next level.

Integrating SwiftUI into UIKit Apps by Natalia Panferova book coverIntegrating SwiftUI into UIKit Apps by Natalia Panferova book cover

Enhance older apps with SwiftUI!$45

A detailed guide on gradually adopting SwiftUI in UIKit projects

Integrating SwiftUI into UIKit Appsby Natalia Panferova

  • Upgrade your apps with new features like Swift Charts and Widgets
  • Support older iOS versions with effective backward-compatible strategies
  • Seamlessly bridge state and data between UIKit and SwiftUI using the latest APIs

Enhance older apps with SwiftUI!

A detailed guide on gradually adopting SwiftUI in UIKit projects

Integrating SwiftUI into UIKit Apps by Natalia Panferova book coverIntegrating SwiftUI into UIKit Apps by Natalia Panferova book cover

Integrating SwiftUI
into UIKit Apps

by Natalia Panferova

$45