UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SOLVED: Alert button color conforming to .accentColor?

Forums > SwiftUI

Does anyone know if there is a way to get .accentColor to apply to alert buttons? My alert is nested well inside where I set my .accentColor(.red) but when the alert opens my dismiss button remains blue.

2      

There is no way to change the color of a button in an Alert. You might be able to use UIViewControllerRepresentable to wrap a UIAlertController and then set the controller's tintColor but why go to all that effort? Just let the system do its thing.

Also, using an accentColor of red for an alert button is potentially confusing to the user because a red color indicates a button for a destructive action. You should rethink that.

2      

I take your point about it potentially being confusing, but it seems a bit odd because Apple does theme alert buttons in their own apps with accentColor (or maybe they are using tintColor?). Yellow in Notes, Red in Music and Calendars, Purple in Podcasts, etc. When you have a color theme running throughout your UI it is rather jarring to suddenly have an alert pop up with buttons in a different color. That said, I'm just starting out here with SwiftUI and that potential workaround to the problem sounds rather complicated so I might be rather stuck until Apple can fix it in SwiftUI.

2      

Here is how you can do it:

Step 1. Go to Assets.xcassets and in Colors folder add your custom color with a name myCustomColor

Step 2. You need to write an extension to Color. I add such things in DesignSystem.swift I create for all the custom fonts and colors I am using.

extension Color {
    public static let myCustomColor = Color("myCustomColor")
}

Step 3. Add the following code in SceneDelegate inside func scene(_...

UIView.appearance(whenContainedInInstancesOf: [UIAlertController.self]).tintColor = UIColor(Color.myCustomColor)

2      

@kslazinski Cool, didn't know that!

If you're using the SwiftUI lifecycle, in which there is no SceneDelegate anymore, you can put that into the init method of a View where you call Alert or even your App struct and it will work.

A caveat, though: This only works because currently SwiftUI uses a UIAlertController behind the scenes of Alert. If that changes in a future version of SwiftUI (like how in iOS 13 List was backed by a UITableVIew but in iOS 14 it no longer is), then it will stop working.

But still, a good tool to have in the toolkit!

4      

If you're using the SwiftUI lifecycle, in which there is no SceneDelegate anymore, you can put that into the init method of a View where you call Alert or even your App struct and it will work.

While the workaround looks pretty easy (just a single line of code - thanks @kslazinski), I am using SwiftUI as you describe @roosterboy and I'm not quite following what you mean by putting this into the init method of a View or the App struct (the latter likely being the place I would want to add it so it could apply to any alerts I might want to present anywhere in my app). Could you please elaborate... or if Paul has covered that, could you please point me in the right direction to go review that as I don't recall seeing anything like this in 100 Days Of SwiftUI or in going through SwiftUI by Example but it could be that I'm just not connecting something presented there with what you are describing as this is all still pretty new to me.

2      

I did some digging online. Well, that was far easier than I was thinking and it seems to be working fine:

    init() {
        UIView.appearance(whenContainedInInstancesOf: [UIAlertController.self]).tintColor = .systemRed
    }

Regarding the caution in case things change around behind the scenes, I added a little note to myself to check (simple as just commenting out the code above and seeing what happens) when SwiftUI is updated. If Apple changes things behind the scenes instead of using UIAlertController (or not), hopefully at some point they will just pass along the .accentColor so the workaround is no longer needed at all.

Thanks again @kslazinski and @roosterboy

4      

Thanks for the tip @roosterboy I am planning to move my app to SwiftUI 2 soon (that's how it's called? the one without scenedelegate). So your tip on how to make it work there will be useful

Yup, @MikeYenco I also hope it will be easier soon. I hope that we will see a native SwiftUI alerts after WWDC this year

2      

I tried @MikeYenco's code and it works fine. Thank you all for your comments.

So, then I tried to use my AccentColor defined in my assets catalog. My AccentColor has three colors: any, light and dark.

UIView.appearance(whenContainedInInstancesOf: [UIAlertController.self])
  .tintColor = UIColor(Color("AccentColor"))

It gets the right color when in light appaerance, but the dark appaerance color is not used when the user interface style is set to dark. The light appaerance color is the only one used.

Then, I tried this:

UIView.appearance(for: UITraitCollection(userInterfaceStyle: .light),
  whenContainedInInstancesOf: [UIAlertController.self])
    .tintColor = UIColor(Color("AccentColor"))

UIView.appearance(for: UITraitCollection(userInterfaceStyle: .dark),
  whenContainedInInstancesOf: [UIAlertController.self])
    .tintColor = UIColor(Color("AccentColor"))

In this case, it works as before: in both light mode and dark mode it always uses the color for the light appaerance.

Then, I tried setting the colors directly in code, instead of using my AccentColor defined in my asset catalog.

UIView.appearance(for: UITraitCollection(userInterfaceStyle: .light),
  whenContainedInInstancesOf: [UIAlertController.self])
    .tintColor = UIColor(red: 50, green: 50, blue: 100, alpha: 1)
UIView.appearance(for: UITraitCollection(userInterfaceStyle: .dark),
  whenContainedInInstancesOf: [UIAlertController.self])
    .tintColor = UIColor(red: 150, green: 150, blue: 250, alpha: 1)

In this case, the OK button is always using a pure white color.

Does anybody know how to use properly do this? I want the system to chose the correct color based on the user interface style, using the AccentColor I have defined in my assets catalog.

I am fairly new to development for Apple devices, so, please, bear with me.

2      

Hacking with Swift is sponsored by RevenueCat

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.