147

The issue I am having is that I want to be able to change the textColor of certain text in a TextView. I am using a concatenated string, and just want the strings I am appending into the TextView's text. It appears that what I want to use is NSMutableAttributedString, but I am not finding any resources of how to use this in Swift. What I have so far is something like this:

let string = "A \(stringOne) with \(stringTwo)"
var attributedString = NSMutableAttributedString(string: string)
textView.attributedText = attributedString

From here I know I need to find the range of words that need to have their textColor changed and then add them to the attributed string. What I need to know is how to find the correct strings from the attributedString, and then change their textColor.

Since I have too low of a rating I can't answer my own question, but here is the answer I found

I found my own answer by translating from translating some code from

Change attributes of substrings in a NSAttributedString

Here is the example of implementation in Swift:

let string = "A \(stringOne) and \(stringTwo)"
var attributedString = NSMutableAttributedString(string:string)

let stringOneRegex = NSRegularExpression(pattern: nameString, options: nil, error: nil)
let stringOneMatches = stringOneRegex.matchesInString(longString, options: nil, range: NSMakeRange(0, attributedString.length))
for stringOneMatch in stringOneMatches {
    let wordRange = stringOneMatch.rangeAtIndex(0)
    attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.nameColor(), range: wordRange)
}

textView.attributedText = attributedString

Since I am wanting to change the textColor of multiple Strings I will make a helper function to handle this, but this works for changing the textColor.

2
  • Do you know how to do it in Objective-C? Have you attempted rewriting that same code in Swift? Commented Aug 8, 2014 at 16:01
  • Here is a really good answer: stackoverflow.com/a/37992022/426571 Commented Apr 29, 2020 at 1:30

25 Answers 25

154
let mainString = "Hello World"
let stringToColor = "World"

SWIFT 5

let range = (mainString as NSString).range(of: stringToColor)

let mutableAttributedString = NSMutableAttributedString.init(string: mainString)
mutableAttributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.red, range: range)

textField = UITextField.init(frame: CGRect(x:10, y:20, width:100, height: 100))
textField.attributedText = mutableAttributedString

SWIFT 4.2

let range = (mainString as NSString).range(of: stringToColor)
    

let mutableAttributedString = NSMutableAttributedString.init(string: mainString)
mutableAttributedString.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor.red, range: range)     
    
textField = UITextField.init(frame: CGRect(x:10, y:20, width:100, height: 100))
textField.attributedText = mutableAttributedString
Sign up to request clarification or add additional context in comments.

1 Comment

what if the string is big, and has many duplicated (similar) words. will range(of: ... ) works?
113

I see you have answered the question somewhat, but to provide a slightly more concise way without using regex to answer to the title question:

To change the colour of a length of text you need to know the start and end index of the coloured-to-be characters in the string e.g.

var mainString = "Hello World"
var stringToColor = "World"

var range = (mainString as NSString).range(of: stringToColor)

Then you convert to attributed string and use 'add attribute' with NSForegroundColorAttributeName:

var attributedString = NSMutableAttributedString(string: mainString)
attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: .red , range: range)

A list of further standard attributes you can set can be found in Apple's documentation

3 Comments

NSColor is OSX only - use UIColor for IOS
What if i have var main_string = "Hello World Hello World Hello World" and i need to apply color on "World" in whole string?
main_string, string_to_color and range were never mutated. Consider changing them to let constant?
48

Swift 2.1 Update:

 let text = "We tried to make this app as most intuitive as possible for you. If you have any questions don't hesitate to ask us. For a detailed manual just click here."
 let linkTextWithColor = "click here"

 let range = (text as NSString).rangeOfString(linkTextWithColor)

 let attributedString = NSMutableAttributedString(string:text)
 attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor() , range: range)

 self.helpText.attributedText = attributedString

self.helpText is a UILabel outlet.

3 Comments

Oh Chris, u are my hero. I am searching for this exactly code block for a long time.
@chris . I want to change nsmutableattributed string in textview ,is that possible
it's work for single word.but in my string there are multiple word it's color change but then i write after that red color word that word's color is also red.so can you give any solution if you have.
36

Swift 4.2 and Swift 5 colorise parts of the string.

A very easy way to use NSMutableAttributedString while extending the String. This also can be used to colourize more than one word in the whole string.

import UIKit

extension String {
func attributedStringWithColor(_ colorizeWords: [String], color: UIColor, characterSpacing: UInt? = nil, boldWords: [String] = []) -> NSAttributedString {
        // Create a mutable attributed string based on the original string.
        let attributedString = NSMutableAttributedString(string: self)

        // Apply color and bold attributes to the specified words.
        colorizeWords.forEach { word in
            let range = (self as NSString).range(of: word)

            attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: color, range: range)

            if boldWords.contains(word) {
                // Make the specified words bold.
                attributedString.addAttribute(NSAttributedString.Key.font, value: UIFont.boldSystemFont(ofSize: UIFont.systemFontSize), range: range)
            }
        }

        // Apply character spacing if specified.
        guard let characterSpacing = characterSpacing else {
            return attributedString
        }

        attributedString.addAttribute(NSAttributedString.Key.kern, value: characterSpacing, range: NSRange(location: 0, length: attributedString.length))

        return attributedString
    }
}

Now you can use globally at any viewcontroller you want:

let attributedWithTextColor: NSAttributedString = "Doc, welcome back :)".attributedStringWithColor(["Doc", "back"], color: UIColor.black)

myLabel.attributedText = attributedWithTextColor

Example of using text colouring with swift 4

Comments

11

Answer is already given in previous posts but i have a different way of doing this

Swift 3x :

var myMutableString = NSMutableAttributedString()

myMutableString = NSMutableAttributedString(string: "Your full label textString")

myMutableString.setAttributes([NSFontAttributeName : UIFont(name: "HelveticaNeue-Light", size: CGFloat(17.0))!
        , NSForegroundColorAttributeName : UIColor(red: 232 / 255.0, green: 117 / 255.0, blue: 40 / 255.0, alpha: 1.0)], range: NSRange(location:12,length:8)) // What ever range you want to give

yourLabel.attributedText = myMutableString

Hope this helps anybody!

4 Comments

@UmaMadhavi What is your requirement exactly?
I want to change font size & font color in textview. I am getting it in nsmutableattributedstring.
@UmaMadhavi check out this link1 and link2. It may be helpful!
Crashes if font isn't available.
10

Chris' answer was a great help to me, so I used his approach and turned into a func that I can reuse. This let's me assign a color to a substring while giving the rest of the string another color.

static func createAttributedString(fullString: String, fullStringColor: UIColor, subString: String, subStringColor: UIColor) -> NSMutableAttributedString
{
    let range = (fullString as NSString).rangeOfString(subString)
    let attributedString = NSMutableAttributedString(string:fullString)
    attributedString.addAttribute(NSForegroundColorAttributeName, value: fullStringColor, range: NSRange(location: 0, length: fullString.characters.count))
    attributedString.addAttribute(NSForegroundColorAttributeName, value: subStringColor, range: range)
    return attributedString
}

Comments

8

Swift 4.1

NSAttributedStringKey.foregroundColor

for example if you want to change font in NavBar:

self.navigationController?.navigationBar.titleTextAttributes = [ NSAttributedStringKey.font: UIFont.systemFont(ofSize: 22), NSAttributedStringKey.foregroundColor: UIColor.white]

Comments

6

You can use this extension I test it over

swift 4.2

import Foundation
import UIKit

extension NSMutableAttributedString {

    convenience init (fullString: String, fullStringColor: UIColor, subString: String, subStringColor: UIColor) {
           let rangeOfSubString = (fullString as NSString).range(of: subString)
           let rangeOfFullString = NSRange(location: 0, length: fullString.count)//fullString.range(of: fullString)
           let attributedString = NSMutableAttributedString(string:fullString)
           attributedString.addAttribute(NSAttributedStringKey.foregroundColor, value: fullStringColor, range: rangeOfFullString)
           attributedString.addAttribute(NSAttributedStringKey.foregroundColor, value: subStringColor, range: rangeOfSubString)

           self.init(attributedString: attributedString)
   }

}

Comments

4

Swift 2.2

var myMutableString = NSMutableAttributedString()

myMutableString = NSMutableAttributedString(string: "1234567890", attributes: [NSFontAttributeName:UIFont(name: kDefaultFontName, size: 14.0)!])

myMutableString.addAttribute(NSForegroundColorAttributeName, value: UIColor(red: 0.0/255.0, green: 125.0/255.0, blue: 179.0/255.0, alpha: 1.0), range: NSRange(location:0,length:5))

self.lblPhone.attributedText = myMutableString

3 Comments

I get an error when I do this. I think you want this without .CGColor.
@SarabjitSingh. how can this is possible for textview
@UmaMadhavi ... You just need to add self.textView.attributedText = myMutableString ..... It will work...
4

Easiest way to do label with different style such as color, font etc. is use property "Attributed" in Attributes Inspector. Just choose part of text and change it like you want

enter image description here

1 Comment

Suposing you're not changing the strings programatically
4

Based on the answers before I created a string extension

extension String {

func highlightWordsIn(highlightedWords: String, attributes: [[NSAttributedStringKey: Any]]) -> NSMutableAttributedString {
     let range = (self as NSString).range(of: highlightedWords)
     let result = NSMutableAttributedString(string: self)

     for attribute in attributes {
         result.addAttributes(attribute, range: range)
     }

     return result
    }
}

You can pass the attributes for the text to the method

Call like this

  let attributes = [[NSAttributedStringKey.foregroundColor:UIColor.red], [NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: 17)]]
  myLabel.attributedText = "This is a text".highlightWordsIn(highlightedWords: "is a text", attributes: attributes)

Comments

4

Swift 4.1

I have changed from this In Swift 3

let str = "Welcome "
let welcomeAttribute = [ NSForegroundColorAttributeName: UIColor.blue()]
let welcomeAttrString = NSMutableAttributedString(string: str, attributes: welcomeAttribute)

And this in Swift 4.0

let str = "Welcome "
let welcomeAttribute = [ NSAttributedStringKey.foregroundColor: UIColor.blue()]
let welcomeAttrString = NSMutableAttributedString(string: str, attributes: welcomeAttribute)

to Swift 4.1

let str = "Welcome "
let welcomeAttribute = [ NSAttributedStringKey(rawValue: NSForegroundColorAttributeName): UIColor.blue()]
let welcomeAttrString = NSMutableAttributedString(string: str, attributes: welcomeAttribute)

Works fine

1 Comment

This is changing the entire string? This is the most readable to me, but Is there a way to change only specific words within the string like the OP asked.
3

swift 4.2

    let textString = "Hello world"
    let range = (textString as NSString).range(of: "world")
    let attributedString = NSMutableAttributedString(string: textString)

    attributedString.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor.red, range: range)
    self.textUIlable.attributedText = attributedString

Comments

3

This might be work for you

let main_string = " User not found,Want to review ? Click here"
    let string_to_color = "Click here"

    let range = (main_string as NSString).range(of: string_to_color)

    let attribute = NSMutableAttributedString.init(string: main_string)
    attribute.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor.blue , range: range)

    lblClickHere.attributedText = attribute

1 Comment

While this code snippet may be the solution, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion.
3

With this simple function you can assign the text and highlight the chosen word.

You can also change the UITextView to UILabel, etc.

func highlightBoldWordAtLabel(textViewTotransform: UITextView, completeText: String, wordToBold: String){
    textViewToTransform.text = completeText
    let range = (completeText as NSString).range(of: wordToBold)
    let attribute = NSMutableAttributedString.init(string: completeText)

    attribute.addAttribute(NSAttributedString.Key.font, value: UIFont.boldSystemFont(ofSize: 16), range: range)
    attribute.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.black , range: range)
    textViewToTransform.attributedText = attribute
}

Comments

3

This extension works well when configuring the text of a label with an already set default color.

public extension String {
    func setColor(_ color: UIColor, ofSubstring substring: String) -> NSMutableAttributedString {
        let range = (self as NSString).range(of: substring)
        let attributedString = NSMutableAttributedString(string: self)
        attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: color, range: range)
        return attributedString
    }
}

For example

let text = "Hello World!"
let attributedText = text.setColor(.blue, ofSubstring: "World")

let myLabel = UILabel()
myLabel.textColor = .white
myLabel.attributedText = attributedText

Comments

2

For everyone who are looking for "Applying specific color to multiple words in text", we can do it using NSRegularExpression

 func highlight(matchingText: String, in text: String) {
    let attributedString  = NSMutableAttributedString(string: text)
    if let regularExpression = try? NSRegularExpression(pattern: "\(matchingText)", options: .caseInsensitive) {
        let matchedResults = regularExpression.matches(in: text, options: [], range: NSRange(location: 0, length: attributedString.length))
        for matched in matchedResults {
             attributedString.addAttributes([NSAttributedStringKey.backgroundColor : UIColor.yellow], range: matched.range)

        }
        yourLabel.attributedText = attributedString
    }
}

Reference link : https://gist.github.com/aquajach/4d9398b95a748fd37e88

1 Comment

Is it possible to use your code in MacOS cocoa app? I tried to use it in my cocoa project, but there's no .attributedText in cocoa NSTextView.
2

You can use as simple extension

extension String{

func attributedString(subStr: String) -> NSMutableAttributedString{
    let range = (self as NSString).range(of: subStr)
    let attributedString = NSMutableAttributedString(string:self)
    attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.red , range: range)
    
    return attributedString
  }
}

myLable.attributedText = fullStr.attributedString(subStr: strToChange)

  

Comments

1

Super easy way to do this.

let text = "This is a colorful attributed string"
let attributedText = 
NSMutableAttributedString.getAttributedString(fromString: text)
attributedText.apply(color: .red, subString: "This")
//Apply yellow color on range
attributedText.apply(color: .yellow, onRange: NSMakeRange(5, 4))

For more detail click here: https://github.com/iOSTechHub/AttributedString

1 Comment

Excellent, thank you. After implementing the class referenced from the link on GitHub this did exactly what I was looking for.
1

To change color of the font colour, first select attributed instead of plain like in the image below

You then need to select the text in the attributed field and then select the color button on the right-hand side of the alignments. This will change the color.

Comments

1

You can use this method. I implemented this method in my common utility class to access globally.

func attributedString(with highlightString: String, normalString: String, highlightColor: UIColor) -> NSMutableAttributedString {
    let attributes = [NSAttributedString.Key.foregroundColor: highlightColor]
    let attributedString = NSMutableAttributedString(string: highlightString, attributes: attributes)
    attributedString.append(NSAttributedString(string: normalString))
    return attributedString
}

Comments

0

If you are using Swift 3x and UITextView, maybe the NSForegroundColorAttributeName won't work (it didn't work for me no matter what approach I tried).

So, after some digging around I found a solution.

//Get the textView somehow
let textView = UITextView()
//Set the attributed string with links to it
textView.attributedString = attributedString
//Set the tint color. It will apply to the link only
textView.tintColor = UIColor.red

Comments

0

You need to change textview parameters, not parameters of attributed string

textView.linkTextAttributes = [
        NSAttributedString.Key.foregroundColor: UIColor.red,
        NSAttributedString.Key.underlineColor: UIColor.red,
        NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue
    ]

Comments

0

Please check cocoapod Prestyler:

Prestyler.defineRule("$", UIColor.orange)
label.attributedText = "This $text$ is orange".prestyled()

Comments

0
extension String{
// to make text field mandatory * looks
mutating func markAsMandatoryField()-> NSAttributedString{

    let main_string = self
    let string_to_color = "*"
    let range = (main_string as NSString).range(of: string_to_color)
    print("The rang = \(range)")
    let attribute = NSMutableAttributedString.init(string: main_string)
    attribute.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.rgbColor(red: 255.0, green: 0.0, blue: 23.0) , range: range)
     return attribute
}

}

use EmailLbl.attributedText = EmailLbl.text!.markAsMandatoryField()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.