NEW: Start my new Ultimate Portfolio App course with a free Hacking with Swift+ trial! >>

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.

   

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.

   

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.

   

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)

   

@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!

2      

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.

   

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

1      

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

   

Hacking with Swift is sponsored by Instabug

SPONSORED Catch bugs as soon as they happen and know exactly why a crash occurred. Instabug's SDK grabs all the logs they need to fix bugs, crashes and performance issues in minutes instead of days. Get screenshots, device details, network logs, repro steps, and tons of other critical insights needed to resolve issues and prioritize product backlogs straight from your dashboard. It only takes a minute to integrate!

Get started now

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

Reply to this topic…

You need to create an account or log in to reply.

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.