19

How do I change the UIAlertController's Title font using Swift?

I'm not talking about the message color, I'm not talking about the buttons color.

I'm talking about the Title.

Jonathan Soifer
  • 2,715
  • 6
  • 27
  • 50

6 Answers6

47
let attributedString = NSAttributedString(string: "Title", attributes: [
    NSFontAttributeName : UIFont.systemFontOfSize(15), //your font here
    NSForegroundColorAttributeName : UIColor.redColor()
])

let alert = UIAlertController(title: "", message: "",  preferredStyle: .alert)

alert.setValue(attributedString, forKey: "attributedTitle")

let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (_) in
}

alert.addAction(cancelAction)

present(alert, animated: true, completion: nil)

Added the correct line of code to my answer as it's much more concise than the answer below.

Adil Hussain
  • 30,049
  • 21
  • 112
  • 147
pbush25
  • 5,228
  • 2
  • 26
  • 35
  • 4
    Works greta. Can anyone confirm that accessing the property `attributedTitle` via KVO does _**not**_ count as using a private API? – Nicolas Miari Jul 01 '16 at 10:25
  • 2
    @NicolasMiari The `attributedTitle` property is not part of the public API for [UIAlertController](https://developer.apple.com/reference/uikit/uialertcontroller) and is therefore considered private ([clause 2.5.1](https://developer.apple.com/app-store/review/guidelines/#software-requirements)). Submit a feature request using the [Bug Reporter](https://bugreport.apple.com)! – jamesk Mar 10 '17 at 20:22
  • @jamesk you're not wrong but the number of upvotes this answer has suggests people haven't had any problems using it. – pbush25 Mar 10 '17 at 20:24
  • 5
    @pbush25 You may be right. Another possibility is that, during development, devs upvote answers that appear to work, and later when apps are rejected, devs grind their teeth in frustration but don't bother to go back and downvote all the answers they upvoted. Who can say? To be fair, use of a key as generic as `attributedTitle` certainly looks innocuous, so it at least has that much going for it. – jamesk Mar 10 '17 at 20:37
  • @jamesk no one is asking you to use it. For all you know these may all be for apps that are never going to the App Store. The warning has been there since this answer was created so people were aware of the possibility it may not make it through review. – pbush25 Mar 10 '17 at 20:39
  • Sure. I was seeking to answer the question asked by @NicolasMiari, and I think we've achieved that. – jamesk Mar 10 '17 at 20:43
  • 1
    I did see on the Apple forums where other developers were having truncation issues when they used a custom font (since evidently all sizing is done using the system font). So given this issue could arise, and Apple does not officially support this, I would be leery against doing it. – GilroyKilroy Feb 05 '18 at 19:43
10
Alert(self, Title: “Hello”, TitleColor: UIColor.whiteColor(), Message: “World”, MessageColor: UIColor.whiteColor(), BackgroundColor: UIColor.blackColor(), BorderColor: UIColor.yellowColor(), ButtonColor: UIColor.yellowColor())
    func Alert(View: ViewController, Title: String, TitleColor: UIColor, Message: String, MessageColor: UIColor, BackgroundColor: UIColor, BorderColor: UIColor, ButtonColor: UIColor) {

    let TitleString = NSAttributedString(string: Title, attributes: [NSFontAttributeName : UIFont.systemFontOfSize(15), NSForegroundColorAttributeName : TitleColor])
    let MessageString = NSAttributedString(string: Message, attributes: [NSFontAttributeName : UIFont.systemFontOfSize(15), NSForegroundColorAttributeName : MessageColor])

    let alertController = UIAlertController(title: Title, message: Message, preferredStyle: .Alert)

    alertController.setValue(TitleString, forKey: "attributedTitle")
    alertController.setValue(MessageString, forKey: "attributedMessage")

    let okAction = UIAlertAction(title: "OK", style: .Default) { (action) in

    }

    let cancelAction = UIAlertAction(title: "Cancel", style: .Default, handler: nil)

    alertController.addAction(okAction)
    alertController.addAction(cancelAction)


    let subview = alertController.view.subviews.first! as UIView
    let alertContentView = subview.subviews.first! as UIView
    alertContentView.backgroundColor = BackgroundColor
    alertContentView.layer.cornerRadius = 10
    alertContentView.alpha = 1
    alertContentView.layer.borderWidth = 1
    alertContentView.layer.borderColor = BorderColor.CGColor


    //alertContentView.tintColor = UIColor.whiteColor()
    alertController.view.tintColor = ButtonColor

    View.presentViewController(alertController, animated: true) {
        // ...
    }
}
ulentini
  • 2,413
  • 1
  • 14
  • 26
user2643679
  • 706
  • 12
  • 18
9

What push25 said is correct, only you have to use key-value coding in order to set the attributed string. (Thanks dupuis2387)

    //Define a color
    let color = UIColor.redColor()

    //Make a controller
    let alertVC = UIAlertController(title: "Dont care what goes here, since we're about to change below", message: "", preferredStyle: UIAlertControllerStyle.Alert)

    //Title String
    var hogan = NSMutableAttributedString(string: "Presenting the great... Hulk Hogan!")

    //Make the attributes, like size and color
    hogan.addAttribute(NSFontAttributeName, value: UIFont.systemFontOfSize(40.0), range: NSMakeRange(24, 11))

    hogan.addAttribute(NSForegroundColorAttributeName, value: color, range: NSMakeRange(0, NSString(string: hogan.string).length))

    //Set the new title
    //Use "attributedMessage" for the message
    alertVC.setValue(hogan, forKey: "attributedTitle")

    //This will change the button color
    alertVC.view.tintColor = UIColor.orangeColor()

    //Make the button
    let button:UIAlertAction  = UIAlertAction(title: "Label text", style: UIAlertActionStyle.Default, handler: { (e:UIAlertAction!) -> Void in
        println("\(e)")
    })

    //You can add images to the button
    let accessoryImage:UIImage = UIImage(named: "someImage")!
    button.setValue(accessoryImage, forKey:"image")

    //Add the button to the alert
    alertVC.addAction(button)

    //Finally present it
    self.presentViewController(alertVC, animated: true, completion:  nil)
Community
  • 1
  • 1
Ignat
  • 1,142
  • 1
  • 12
  • 22
  • 1
    //This will change the button color alertVC.view.tintColor = UIColor.orangeColor() is not supported correctly in iOS 9 – Hassan Taleb Sep 19 '15 at 10:23
  • 1
    @HassanTaleb - Because this does not work in iOS 9, here is a workaround for setting the `tintColor` of a `UIAlertController` button: http://stackoverflow.com/a/32636878/4376309 – peacetype Oct 30 '15 at 21:33
3

I construct this class:

class Alert {
class func showAlert(title: String, titleColor: UIColor, message: String, preferredStyle: UIAlertControllerStyle, titleAction: String, actionStyle: UIAlertActionStyle, vc: UIViewController) {

    let attributedString = NSAttributedString(string: title, attributes: [NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: 16), NSAttributedStringKey.foregroundColor: titleColor])
    let alert = UIAlertController(title: title, message: message, preferredStyle: preferredStyle)

    alert.setValue(attributedString, forKey: "attributedTitle")

    alert.addAction(UIAlertAction(title: titleAction, style: actionStyle, handler: nil))
    vc.present(alert, animated: true)
}

}

Usage

Alert.showAlert(title: "yourTitle", titleColor: .yourcolor, message: "your message", preferredStyle: .alert, titleAction: "your title action", actionStyle: .yourActionStyle, vc: self)

Hope this help :)

Fabio
  • 5,432
  • 4
  • 22
  • 24
2

Here is for Swift 4 ++ also using a global instance for UIAlert

func showAlertError(withTitle title: String, withMessage message: String) {
    var dialogTitle = title
    if dialogTitle.isEmpty { dialogTitle = "Error:" }


    let attributedString = NSAttributedString(string: dialogTitle, attributes: [
        NSAttributedString.Key.font : UIFont.systemFont(ofSize: 15),
        NSAttributedString.Key.foregroundColor : UIColor.red
        ])

    let alert = UIAlertController(title: "", message: message, preferredStyle: .alert)
    alert.setValue(attributedString, forKey: "attributedTitle")
    let ok = UIAlertAction(title: "OK", style: .default, handler: nil)

    alert.addAction(ok)
    DispatchQueue.main.async(execute: {
        self.present(alert, animated: true)
    })
}
Mr T
  • 1,409
  • 1
  • 17
  • 24
-1

Also you can add a UIAlertAction with title " "(space) and add a custom UILabel to UIAlertController.view at the place of title.

xc000
  • 9
  • 1