How to underline a UILabel in swift?

142,321

Solution 1

You can do this using NSAttributedString

Example:

let underlineAttribute = [NSAttributedString.Key.underlineStyle: NSUnderlineStyle.thick.rawValue]
let underlineAttributedString = NSAttributedString(string: "StringWithUnderLine", attributes: underlineAttribute)
myLabel.attributedText = underlineAttributedString

EDIT

To have the same attributes for all texts of one UILabel, I suggest you to subclass UILabel and overriding text, like that:

Swift 5

Same as Swift 4.2 but: You should prefer the Swift initializer NSRange over the old NSMakeRange, you can shorten to .underlineStyle and linebreaks improve readibility for long method calls.

class UnderlinedLabel: UILabel {

override var text: String? {
    didSet {
        guard let text = text else { return }
        let textRange = NSRange(location: 0, length: text.count)
        let attributedText = NSMutableAttributedString(string: text)
        attributedText.addAttribute(.underlineStyle,
                                    value: NSUnderlineStyle.single.rawValue,
                                    range: textRange)
        // Add other attributes if needed
        self.attributedText = attributedText
        }
    }
}

Swift 4.2

class UnderlinedLabel: UILabel {

override var text: String? {
    didSet {
        guard let text = text else { return }
        let textRange = NSMakeRange(0, text.count)
        let attributedText = NSMutableAttributedString(string: text)
        attributedText.addAttribute(NSAttributedString.Key.underlineStyle , value: NSUnderlineStyle.single.rawValue, range: textRange)
        // Add other attributes if needed
        self.attributedText = attributedText
        }
    }
}

Swift 3.0

class UnderlinedLabel: UILabel {
    
    override var text: String? {
        didSet {
            guard let text = text else { return }
            let textRange = NSMakeRange(0, text.characters.count)
            let attributedText = NSMutableAttributedString(string: text)
            attributedText.addAttribute(NSUnderlineStyleAttributeName , value: NSUnderlineStyle.styleSingle.rawValue, range: textRange)
            // Add other attributes if needed
            self.attributedText = attributedText
        }
    }
}

And you put your text like this :

@IBOutlet weak var label: UnderlinedLabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        label.text = "StringWithUnderLine"
    }

OLD:

Swift (2.0 to 2.3):

class UnderlinedLabel: UILabel {
    
    override var text: String? {
        didSet {
            guard let text = text else { return }
            let textRange = NSMakeRange(0, text.characters.count)
            let attributedText = NSMutableAttributedString(string: text)
            attributedText.addAttribute(NSUnderlineStyleAttributeName, value:NSUnderlineStyle.StyleSingle.rawValue, range: textRange)
            // Add other attributes if needed
            
            self.attributedText = attributedText
        }
    }
}

Swift 1.2:

class UnderlinedLabel: UILabel {
    
    override var text: String! {
        didSet {
            let textRange = NSMakeRange(0, count(text))
            let attributedText = NSMutableAttributedString(string: text)
            attributedText.addAttribute(NSUnderlineStyleAttributeName, value:NSUnderlineStyle.StyleSingle.rawValue, range: textRange)
            // Add other attributes if needed
            
            self.attributedText = attributedText
        }
    }
}

Solution 2

Swift 5 & 4.2 one liner:

label.attributedText = NSAttributedString(string: "Text", attributes:
    [.underlineStyle: NSUnderlineStyle.single.rawValue])

Swift 4 one liner:

label.attributedText = NSAttributedString(string: "Text", attributes:
    [.underlineStyle: NSUnderlineStyle.styleSingle.rawValue])

Swift 3 one liner:

label.attributedText = NSAttributedString(string: "Text", attributes:
      [NSUnderlineStyleAttributeName: NSUnderlineStyle.styleSingle.rawValue])

Solution 3

If you are looking for a way to do this without inheritance:

Swift 5

extension UILabel {
    func underline() {
        if let textString = self.text {
          let attributedString = NSMutableAttributedString(string: textString)
            attributedString.addAttribute(NSAttributedString.Key.underlineStyle,
                                          value: NSUnderlineStyle.single.rawValue,
                                          range: NSRange(location: 0, length: attributedString.length))
          attributedText = attributedString
        }
    }
}

Swift 3/4

// in swift 4 - switch NSUnderlineStyleAttributeName with NSAttributedStringKey.underlineStyle
extension UILabel {
    func underline() {
        if let textString = self.text {
          let attributedString = NSMutableAttributedString(string: textString)
          attributedString.addAttribute(NSUnderlineStyleAttributeName, value: NSUnderlineStyle.styleSingle.rawValue, range: NSRange(location: 0, length: attributedString.length))
          attributedText = attributedString
        }
    }
}


extension UIButton {
  func underline() {
    let attributedString = NSMutableAttributedString(string: (self.titleLabel?.text!)!)
    attributedString.addAttribute(NSUnderlineStyleAttributeName, value: NSUnderlineStyle.styleSingle.rawValue, range: NSRange(location: 0, length: (self.titleLabel?.text!.characters.count)!))
    self.setAttributedTitle(attributedString, for: .normal)
  }
}

Solution 4

Swift 5:

1- Create a String extension to get attributedText

extension String {

    var underLined: NSAttributedString {
        NSMutableAttributedString(string: self, attributes: [.underlineStyle: NSUnderlineStyle.single.rawValue])
    }

}

2- Use it

On buttons:

<#YourButton#>.setAttributedTitle(<#YourButtonTitle#>.underLined, for: .normal)

On Labels:

<#YourLabel#>.attributedText = <#YourLabelTitle#>.underLined

Or Stoyboard version

Solution 5

Just a little fix for the Shlome answer in Swift 4 and Xcode 9.

extension UILabel {
    func underline() {
        if let textString = self.text {
            let attributedString = NSMutableAttributedString(string: textString)
            attributedString.addAttribute(NSAttributedStringKey.underlineStyle,
                                          value: NSUnderlineStyle.styleSingle.rawValue,
                                          range: NSRange(location: 0, length: attributedString.length - 1))
            attributedText = attributedString
        }
    }
}

    extension UIButton {
        func underline() {
            let attributedString = NSMutableAttributedString(string: (self.titleLabel?.text!)!)
            attributedString.addAttribute(NSAttributedStringKey.underlineStyle,
                                          value: NSUnderlineStyle.styleSingle.rawValue,
                                          range: NSRange(location: 0, length: (self.titleLabel?.text!.count)!))
            self.setAttributedTitle(attributedString, for: .normal)
        }
    }
Share:
142,321
Esqarrouth
Author by

Esqarrouth

World-class code copy paster.

Updated on April 17, 2021

Comments

  • Esqarrouth
    Esqarrouth about 3 years

    How to underline a UILabel in Swift? I searched the Objective-C ones but couldn't quite get them to work in Swift.

  • Eric H
    Eric H about 8 years
    This method fails if you rebind the text to the label.
  • meaning-matters
    meaning-matters over 7 years
    @EricH What do you mean?
  • Skaal
    Skaal over 5 years
    NSUnderlineStyle.styleSingle.rawValue has been renamed to NSUnderlineStyle.single.rawValue in swift 4.2
  • N. Der
    N. Der about 5 years
    How do I de-underline?
  • N. Der
    N. Der about 5 years
    What would be the best way to de-underline?
  • byJeevan
    byJeevan almost 5 years
    @N.Der Set again a normal text to label
  • Bruno Muniz
    Bruno Muniz over 4 years
    I've been wondering for a long time: why do we have to use rawValue otherwise it crashes?
  • karthikeyan
    karthikeyan over 4 years
    How you will track the touch?
  • Jan Bergström
    Jan Bergström over 4 years
    simply beutiful and easy
  • Leo Dabus
    Leo Dabus over 4 years
    You should pass UTF16 count instead of the character count when creating your textRange NSRange
  • Leo Dabus
    Leo Dabus over 4 years
    You should pass UTF16 count instead of the character count when creating your NSRange
  • Leo Dabus
    Leo Dabus over 4 years
    You should pass UTF16 count instead of the character count when creating your NSRange
  • Leo Dabus
    Leo Dabus over 4 years
    You should pass UTF16 count instead of the character count when creating your NSRange
  • boherna
    boherna about 4 years
    If you already have the extension for the UILabel, IMO it is simpler to call myButton.titleLabel?.underline(), or at least use it inside the underline() function in the extension for UIButton.
  • João Serra
    João Serra over 3 years
    I've changed this solution to add a underlline on initialize, this way we can use it easily with storyboards required init?(coder: NSCoder) { super.init(coder: coder) self.addUnderline() // your code }
  • Ucdemir
    Ucdemir over 3 years
    Better solution algorithm with better solution you can look my answer stackoverflow.com/questions/28053334/…