4

I've been working on a small project using Xcode. It uses a lot of labels, textfields, etc. I've finished with most of the layout, the constrains, and the forms, titles, etc. After which, the client announces that for all required fields, there should be a red asterisk next to the label.

Call me lazy, but I'd rather not go back to all of my forms, add in a lot of labels with asterisks on them, and re-do my auto-layout to accommodate the new labels.

So, is there a way to change the colour of a specific character (in this case, the asterisk) in a UILabel, while the rest of the text stays black?

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
zack_falcon
  • 4,186
  • 20
  • 62
  • 108
  • Look at using attributed strings which you can set to the label. This allows you to set different colours, as well as font sizes, etc. – totiDev Jan 15 '16 at 09:50
  • `NSMutableAttributedString` does this for you. You can set different property for different range of string. – TheTiger Jan 15 '16 at 10:26
  • Is the effort you would like to achieve it with requires a) not to touch layout code by adding some `UILabel` next to existed `UILabel`s b) not to add asterisk manually to each string you assign to `.text` or `.attributedText` properties of `UILabel`? So, you just want some `UILabel`'s extension or `UILabel`'s subclass with red asterisk being added at the end of each `UILabel` you specify, don't you? – Yevhen Dubinin Jan 15 '16 at 11:57

7 Answers7

10

You can use NSMutableAttributedString. You can set specific range of your string with different color, font, size, ...

E.g:

 var range = NSRange(location:2,length:1) // specific location. This means "range" handle 1 character at location 2

 attributedString = NSMutableAttributedString(string: originalString, attributes: [NSFontAttributeName:UIFont(name: "Georgia", size: 18.0)!])
 // here you change the character to red color
 attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(), range: range)
 label.attributedText = attributedString

Ref: Use multiple font colors in a single label - Swift

You can change a lot of attribute of String. Ref from apple: https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSMutableAttributedString_Class/index.html

Community
  • 1
  • 1
tuledev
  • 10,177
  • 4
  • 29
  • 49
  • This code is copied straight from the top of the answer you're linking to, and in its current form, adds nothing that a comment linked to this thread couldn't have achieved, rather than an answer of your own. Hence, I downvoted this. If you however refine the answer and show the OP how to use this w.r.t. `UILabel`:s (which is his question), I will reverse my down-vote. [See this meta thread](http://meta.stackexchange.com/questions/92505/should-i-flag-answers-which-contain-only-a-link-as-not-an-answer), especially the part in the answer regarding _effort_ by an answerer. – dfrib Jan 15 '16 at 10:54
  • 1
    @dfri Thank you very much. It's really bad. Sorry. I updated my answer for more sense :). I was busy at that time. So I just want the OP see the answer at the link I found. Thank you. :) – tuledev Jan 15 '16 at 12:09
  • You're welcome, and that's better, reversed my vote! – dfrib Jan 15 '16 at 12:35
9
let text = "Sample text *"
let range = (text as NSString).rangeOfString("*")
let attributedString = NSMutableAttributedString(string:text)
attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor() , range: range)

    //Apply to the label
    myLabel.attributedText = attributedString;
Ramesh_T
  • 1,251
  • 8
  • 19
4

UILabel have an .attributedText property of type NSAttributedString.

Declaration

@NSCopying var attributedText: NSAttributedString?

You let your asterix * have a single .redColor() attribute (NSForegroundColorAttributeName), whereas the rest of the new label simply uses the same text as before, however also contained in an NSAttributedTextString.

An example follows below using a function to repeatedly update your existing labels to attributed strings prefixed with a red *:

class ViewController: UIViewController {

    @IBOutlet weak var myFirstLabel: UILabel!
    @IBOutlet weak var mySecondLabel: UILabel!

    let myPrefixCharacter = "*"
    let myPrefixColor = UIColor.redColor()    

    // ...

    override func viewDidLoad() {
        super.viewDidLoad()

        // ...

        /* update labels to attributed strings */
        updateLabelToAttributedString(myFirstLabel)
        updateLabelToAttributedString(mySecondLabel)
        // ...

    }

    func updateLabelToAttributedString(label: UILabel) {

        /* original label text as NSAttributedString, prefixed with " " */
        let attr = [ NSForegroundColorAttributeName: myPrefixColor ]
        let myNewLabelText = NSMutableAttributedString(string: myPrefixCharacter, attributes: attr)
        let myOrigLabelText = NSAttributedString(string: " " + (label.text ?? ""))

        /* set new label text as attributed string */
        myNewLabelText.appendAttributedString(myOrigLabelText)
        label.attributedText = myNewLabelText
    }

    // ...

}

enter image description here

dfrib
  • 70,367
  • 12
  • 127
  • 192
3

Swift 4
(Note: notation for attributed string key is changed in swift 4)

Here is an extension for NSMutableAttributedString, that add/set color on string/text.

extension NSMutableAttributedString {

    func setColor(color: UIColor, forText stringValue: String) {
        let range: NSRange = self.mutableString.range(of: stringValue, options: .caseInsensitive)
        self.addAttribute(NSAttributedStringKey.foregroundColor, value: color, range: range)
    }

}

Now, try above extension with UILabel and see result

let label = UILabel()
label.frame = CGRect(x: 40, y: 100, width: 280, height: 200)
let red = "red"
let blue = "blue"
let green = "green"
let stringValue = "\(red)\n\(blue)\n&\n\(green)"
label.textColor = UIColor.lightGray
label.numberOfLines = 0
let attributedString: NSMutableAttributedString = NSMutableAttributedString(string: stringValue)
attributedString.setColor(color: UIColor.red, forText: red)   // or use direct value for text "red"
attributedString.setColor(color: UIColor.blue, forText: blue)   // or use direct value for text "blue"
attributedString.setColor(color: UIColor.green, forText: green)   // or use direct value for text "green"
label.font = UIFont.systemFont(ofSize: 26)
label.attributedText = attributedString
self.view.addSubview(label)
Krunal
  • 77,632
  • 48
  • 245
  • 261
2
func updateAttributedStringWithCharacter(title : String, uilabel: UILabel) {
    let text = title + "*"
    let range = (text as NSString).range(of: "*")
    let attributedString = NSMutableAttributedString(string:text)
    attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.red , range: range)
    uilabel.attributedText = attributedString }
thevikasnayak
  • 559
  • 5
  • 13
  • updateAttributedStringWithCharacter(title: lbl_name.text!, uilabel: lbl_name) Use this function to show Star(*) after the label Note -: User above function in viewDidLoad() to get effect. Taken ref from @tuledev's answer – thevikasnayak Oct 31 '20 at 06:52
1

I know this is an old post, but i want to share my approach (which is based on the answer from dfri) i just made it a function for convenience.

func lastCharOnColor(label: UILabel, color: UIColor, length: Int) {

    //First we get the text.
    let string = label.text

    //Get number of characters on string and based on that get last character index.
    let characterCounter    = string?.characters.count
    let lastCharacterIndex  = characterCounter!-1

    //Set Range
    let range = NSRange(location: lastCharacterIndex, length: length)
    let attributedString = NSMutableAttributedString(string: string!, attributes: nil)

    //Set label
    attributedString.addAttribute(NSForegroundColorAttributeName, value: color, range: range)
    label.attributedText = attributedString

}

I use this function to just set the last character from a label to a certain color like this:

        lastCharOnColor(label: self.labelname, color: UIColor.red, length: 1)

Hope this helps anyone.

Wilson Muñoz
  • 191
  • 5
  • 7
0

Here is an extension for simply making mandatory labels by appending a red *

Swift 5

extension UILabel {
func makeTextMandatory() {
    let text = self.text ?? "" + " *"
    let range = (text as NSString).range(of: " *")
    let attributedString = NSMutableAttributedString(string:text)
    attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.red , range: range)
    self.attributedText = attributedString
  }
}

Usage :

dobLabel.makeTextMandatory()
Naval Hasan
  • 1,226
  • 1
  • 13
  • 18