Making text bold using attributed string in swift
Asked Answered
S

25

134

I have a string like this

var str = "@text1 this is good @text1"

Now replace text1 with another string, say t 1. I am able to replace the text, but i am not able to bold it. I want to bold the new string t 1, so that the final output will be:

@t 1 this is good @t 1

How can I do it?

All the examples I am seeing are in Objective-C, but I want to do it in Swift.

Spatola answered 13/2, 2015 at 9:17 Comment(3)
You need to decompose you issue: Learn how to "bold": #25200080 Learn how to replace text.Birch
Use this library, it's petty simple. github.com/iOSTechHub/AttributedStringChristmastide
titleLabel.font = UIFont.boldSystemFont(ofSize: 11) working perfectSpeak
W
309

Usage:

let label = UILabel()
label.attributedText =
    NSMutableAttributedString()
        .bold("Address: ")
        .normal(" Kathmandu, Nepal\n\n")
        .orangeHighlight(" Email: ")
        .blackHighlight(" [email protected] ")
        .bold("\n\nCopyright: ")
        .underlined(" All rights reserved. 2020.")

Result:

enter image description here

Here is a neat way to make a combination of bold and normal texts in a single label plus some other bonus methods.

Extension: Swift 5.*

extension NSMutableAttributedString {
    var fontSize:CGFloat { return 14 }
    var boldFont:UIFont { return UIFont(name: "AvenirNext-Bold", size: fontSize) ?? UIFont.boldSystemFont(ofSize: fontSize) }
    var normalFont:UIFont { return UIFont(name: "AvenirNext-Regular", size: fontSize) ?? UIFont.systemFont(ofSize: fontSize)}
    
    func bold(_ value:String) -> NSMutableAttributedString {
        
        let attributes:[NSAttributedString.Key : Any] = [
            .font : boldFont
        ]
        
        self.append(NSAttributedString(string: value, attributes:attributes))
        return self
    }
    
    func normal(_ value:String) -> NSMutableAttributedString {
        
        let attributes:[NSAttributedString.Key : Any] = [
            .font : normalFont,
        ]
        
        self.append(NSAttributedString(string: value, attributes:attributes))
        return self
    }
    /* Other styling methods */
    func orangeHighlight(_ value:String) -> NSMutableAttributedString {
        
        let attributes:[NSAttributedString.Key : Any] = [
            .font :  normalFont,
            .foregroundColor : UIColor.white,
            .backgroundColor : UIColor.orange
        ]
        
        self.append(NSAttributedString(string: value, attributes:attributes))
        return self
    }
    
    func blackHighlight(_ value:String) -> NSMutableAttributedString {
        
        let attributes:[NSAttributedString.Key : Any] = [
            .font :  normalFont,
            .foregroundColor : UIColor.white,
            .backgroundColor : UIColor.black
            
        ]
        
        self.append(NSAttributedString(string: value, attributes:attributes))
        return self
    }
    
    func underlined(_ value:String) -> NSMutableAttributedString {
        
        let attributes:[NSAttributedString.Key : Any] = [
            .font :  normalFont,
            .underlineStyle : NSUnderlineStyle.single.rawValue
            
        ]
        
        self.append(NSAttributedString(string: value, attributes:attributes))
        return self
    }
}

Note: If compiler is missing UIFont/UIColor, replace them with NSFont/NSColor.

Witkowski answered 23/6, 2016 at 12:44 Comment(2)
is it not for swift 2 ?Gaven
A small addition: func bold(_ text:String, _ size:CGFloat). I added size to the bold so I can control it from outside. Also, I missed the AvenirNext-Medium font in this function so took me few minutes to understand why I can't see my font. Heads up.Debatable
T
126
var normalText = "Hi am normal"

var boldText  = "And I am BOLD!"

var attributedString = NSMutableAttributedString(string:normalText)

var attrs = [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 15)]
var boldString = NSMutableAttributedString(string: boldText, attributes:attrs)

attributedString.append(boldString)

When you want to assign it to a label:

yourLabel.attributedText = attributedString
Tosh answered 13/2, 2015 at 9:26 Comment(1)
note: appendAttributedString has been renamed to .append()Dialectal
T
31

edit/update: Xcode 13.1 • Swift 5.5.1

If you know HTML and CSS you can use it to easily control the font style, color and size of your attributed string as follow:

Discussion
The HTML importer should not be called from a background thread (that is, the options dictionary includes documentType with a value of html). It will try to synchronize with the main thread, fail, and time out. Calling it from the main thread works (but can still time out if the HTML contains references to external resources, which should be avoided at all costs). The HTML import mechanism is meant for implementing something like markdown (that is, text styles, colors, and so on), not for general HTML import.


extension StringProtocol {
    var html2AttStr: NSAttributedString? {
        try? NSAttributedString(data: Data(utf8), options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil)

    }
}

"<style type=\"text/css\">#red{color:#F00}#green{color:#0F0}#blue{color: #00F; font-weight: Bold; font-size: 32}</style><span id=\"red\" >Red,</span><span id=\"green\" > Green </span><span id=\"blue\">and Blue</span>".html2AttStr
Tribalism answered 15/2, 2015 at 23:44 Comment(5)
I am trying to implement this in Swift 2 Xcode, but the font is not being applied. Here is the String: <link href=\"https://fonts.googleapis.com/css?family=Frank+Ruhl+Libre\" rel=\"stylesheet\"> <span style=\"font-family: 'Frank Ruhl Libre', sans-serif;\">שלום</span>Rhee
If it style use WebKit to parse HTML strings in NSAttributedString, careful using it in a background thread...Arnaldo
What is the benefits of using this approach rather than @prajeet answer?Gesticulation
@EmreÖnder It is just personal preference. If you know html it will be easier to simply use the extension above.Tribalism
bold doesnt workAlfons
O
30

If you're working with localised strings, you might not be able to rely on the bold string always being at the end of the sentence. If this is the case then the following works well:

e.g. Query "blah" does not match any items

/* Create the search query part of the text, e.g. "blah". 
   The variable 'text' is just the value entered by  the user. */
let searchQuery = "\"\(text)\""

/* Put the search text into the message */
let message = "Query \(searchQuery). does not match any items"

/* Find the position of the search string. Cast to NSString as we want
   range to be of type NSRange, not Swift's Range<Index> */
let range = (message as NSString).rangeOfString(searchQuery)

/* Make the text at the given range bold. Rather than hard-coding a text size,
   Use the text size configured in Interface Builder. */
let attributedString = NSMutableAttributedString(string: message)
attributedString.addAttribute(NSFontAttributeName, value: UIFont.boldSystemFontOfSize(label.font.pointSize), range: range)

/* Put the text in a label */
label.attributedText = attributedString
Orbicular answered 8/12, 2015 at 14:50 Comment(1)
After hours of searching, this is the only answer which found a solution to my problem. +1Crab
P
11

I extended David West's great answer so that you can input a string and tell it all the substrings you would like to embolden:

func addBoldText(fullString: NSString, boldPartsOfString: Array<NSString>, font: UIFont!, boldFont: UIFont!) -> NSAttributedString {
    let nonBoldFontAttribute = [NSFontAttributeName:font!]
    let boldFontAttribute = [NSFontAttributeName:boldFont!]
    let boldString = NSMutableAttributedString(string: fullString as String, attributes:nonBoldFontAttribute)
    for i in 0 ..< boldPartsOfString.count {
        boldString.addAttributes(boldFontAttribute, range: fullString.rangeOfString(boldPartsOfString[i] as String))
    }
    return boldString
}

And then call it like this:

let normalFont = UIFont(name: "Dosis-Medium", size: 18)
let boldSearchFont = UIFont(name: "Dosis-Bold", size: 18)
self.UILabel.attributedText = addBoldText("Check again in 30 days to find more friends", boldPartsOfString: ["Check", "30 days", "find", "friends"], font: normalFont!, boldFont: boldSearchFont!)

This will embolden all the substrings you want bolded in your given string

Popular answered 23/8, 2016 at 18:57 Comment(1)
Is it possible to have same word bold in two different places? EX: "Check again in 30 days to find 30 friends". How do you make both "30" bold? Thanks in advance.Tempting
W
11

Swift 4 and higher

For Swift 4 and higher that is a good way:

    let attributsBold = [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16, weight: .bold)]
    let attributsNormal = [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16, weight: .regular)]
    var attributedString = NSMutableAttributedString(string: "Hi ", attributes:attributsNormal)
    let boldStringPart = NSMutableAttributedString(string: "John", attributes:attributsBold)
    attributedString.append(boldStringPart)
  
    yourLabel.attributedText = attributedString

In the Label the Text looks like: "Hi John"

Whitcomb answered 4/7, 2019 at 8:25 Comment(0)
C
10

This is the best way that I have come up with. Add a function you can call from anywhere and add it to a file without a class like Constants.swift and then you can embolden words within any string, on numerous occasions by calling just ONE LINE of code:

To go in a constants.swift file:

import Foundation
import UIKit

func addBoldText(fullString: NSString, boldPartOfString: NSString, font: UIFont!, boldFont: UIFont!) -> NSAttributedString {
   let nonBoldFontAttribute = [NSFontAttributeName:font!]
   let boldFontAttribute = [NSFontAttributeName:boldFont!]
   let boldString = NSMutableAttributedString(string: fullString as String, attributes:nonBoldFontAttribute)
   boldString.addAttributes(boldFontAttribute, range: fullString.rangeOfString(boldPartOfString as String))
   return boldString
}

Then you can just call this one line of code for any UILabel:

self.UILabel.attributedText = addBoldText("Check again in 30 DAYS to find more friends", boldPartOfString: "30 DAYS", font: normalFont!, boldFont: boldSearchFont!)


//Mark: Albeit that you've had to define these somewhere:

let normalFont = UIFont(name: "INSERT FONT NAME", size: 15)
let boldFont = UIFont(name: "INSERT BOLD FONT", size: 15)
Civics answered 21/5, 2016 at 1:21 Comment(0)
V
10

Building on Jeremy Bader and David West's excellent answers, a Swift 3 extension:

extension String {
    func withBoldText(boldPartsOfString: Array<NSString>, font: UIFont!, boldFont: UIFont!) -> NSAttributedString {
        let nonBoldFontAttribute = [NSFontAttributeName:font!]
        let boldFontAttribute = [NSFontAttributeName:boldFont!]
        let boldString = NSMutableAttributedString(string: self as String, attributes:nonBoldFontAttribute)
        for i in 0 ..< boldPartsOfString.count {
            boldString.addAttributes(boldFontAttribute, range: (self as NSString).range(of: boldPartsOfString[i] as String))
        }
        return boldString
    }
}

Usage:

let label = UILabel()
let font = UIFont(name: "AvenirNext-Italic", size: 24)!
let boldFont = UIFont(name: "AvenirNext-BoldItalic", size: 24)!
label.attributedText = "Make sure your face is\nbrightly and evenly lit".withBoldText(
    boldPartsOfString: ["brightly", "evenly"], font: font, boldFont: boldFont)
Verruca answered 31/12, 2016 at 16:6 Comment(0)
K
6

usage....

let attrString = NSMutableAttributedString()
            .appendWith(weight: .semibold, "almost bold")
            .appendWith(color: .white, weight: .bold, " white and bold")
            .appendWith(color: .black, ofSize: 18.0, " big black")

two cents...

extension NSMutableAttributedString {

    @discardableResult func appendWith(color: UIColor = UIColor.darkText, weight: UIFont.Weight = .regular, ofSize: CGFloat = 12.0, _ text: String) -> NSMutableAttributedString{
        let attrText = NSAttributedString.makeWith(color: color, weight: weight, ofSize:ofSize, text)
        self.append(attrText)
        return self
    }

}
extension NSAttributedString {

    public static func makeWith(color: UIColor = UIColor.darkText, weight: UIFont.Weight = .regular, ofSize: CGFloat = 12.0, _ text: String) -> NSMutableAttributedString {

        let attrs = [NSAttributedStringKey.font: UIFont.systemFont(ofSize: ofSize, weight: weight), NSAttributedStringKey.foregroundColor: color]
        return NSMutableAttributedString(string: text, attributes:attrs)
    }
}
Kneeland answered 28/3, 2018 at 5:5 Comment(1)
iOS 11 or greater (due to the UIFont.Weight usage).Dialectal
B
5

Accepting as valid the response of Prajeet Shrestha in this thread, I would like to extend his solution using the Label if it is known and the traits of the font.

Swift 4

extension NSMutableAttributedString {

    @discardableResult func normal(_ text: String) -> NSMutableAttributedString {
        let normal = NSAttributedString(string: text)
        append(normal)

        return self
    }

    @discardableResult func bold(_ text: String, withLabel label: UILabel) -> NSMutableAttributedString {

        //generate the bold font
        var font: UIFont = UIFont(name: label.font.fontName , size: label.font.pointSize)!
        font = UIFont(descriptor: font.fontDescriptor.withSymbolicTraits(.traitBold) ?? font.fontDescriptor, size: font.pointSize)

        //generate attributes
        let attrs: [NSAttributedStringKey: Any] = [NSAttributedStringKey.font: font]
        let boldString = NSMutableAttributedString(string:text, attributes: attrs)

        //append the attributed text
        append(boldString)

        return self
    }
}
Buttonhook answered 12/2, 2018 at 3:9 Comment(0)
C
4

Super easy way to do this.

    let text = "This string is having multiple font"
    let attributedText = 
    NSMutableAttributedString.getAttributedString(fromString: text)

    attributedText.apply(font: UIFont.boldSystemFont(ofSize: 24), subString: 
    "This")

    attributedText.apply(font: UIFont.boldSystemFont(ofSize: 24), onRange: 
    NSMakeRange(5, 6))

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

Christmastide answered 2/9, 2018 at 18:14 Comment(3)
How about semi bold?Cantillate
This should be the accepted answer. @Cantillate use the library above and use the apply method with the font you wantUproot
Command .getAttributedString(fromString:) doesn't exist.Jackie
A
4

For -> Search Television by size

1-way using NString and its Range

let query = "Television"
let headerTitle = "size"
let message = "Search \(query) by \(headerTitle)"
let range = (message as NSString).range(of: query)
let attributedString = NSMutableAttributedString(string: message)
attributedString.addAttribute(NSAttributedString.Key.font, value: UIFont.boldSystemFont(ofSize: label1.font.pointSize), range: range)
label1.attributedText = attributedString

another without using NString and its Range

let query = "Television"
let headerTitle = "size"
let (searchText, byText) = ("Search ", " by \(headerTitle)")
let attributedString = NSMutableAttributedString(string: searchText)
let byTextAttributedString = NSMutableAttributedString(string: byText)
let attrs = [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: label1.font.pointSize)]
let boldString = NSMutableAttributedString(string: query, attributes:attrs)
attributedString.append(boldString)
attributedString.append(byTextAttributedString)
label1.attributedText = attributedString

swift5

Alarmist answered 2/4, 2020 at 9:30 Comment(0)
F
2

This could be useful

class func createAttributedStringFrom (string1 : String ,strin2 : String, attributes1 : Dictionary<String, NSObject>, attributes2 : Dictionary<String, NSObject>) -> NSAttributedString{

let fullStringNormal = (string1 + strin2) as NSString
let attributedFullString = NSMutableAttributedString(string: fullStringNormal as String)

attributedFullString.addAttributes(attributes1, range: fullStringNormal.rangeOfString(string1))
attributedFullString.addAttributes(attributes2, range: fullStringNormal.rangeOfString(strin2))
return attributedFullString
}
Fafnir answered 24/12, 2015 at 10:23 Comment(0)
I
2

Swift 3.0

Convert html to string and font change as per your requirement.

do {

     let str = try NSAttributedString(data: ("I'm a normal text and <b>this is my bold part . </b>And I'm again in the normal text".data(using: String.Encoding.unicode, allowLossyConversion: true)!), options: [ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil)

     myLabel.attributedText = str
     myLabel.font =  MONTSERRAT_BOLD(23)
     myLabel.textAlignment = NSTextAlignment.left
} catch {
     print(error)
}


func MONTSERRAT_BOLD(_ size: CGFloat) -> UIFont
{
    return UIFont(name: "MONTSERRAT-BOLD", size: size)!
}
Inspire answered 10/5, 2017 at 11:13 Comment(1)
You should convert your string to data using utf8. Note that Data conforms to collection in Swift 3 so you can initialize Data with your string utf8 collection view Data("I'm a normal text and <b>this is my bold part . </b>And I'm again in the normal text".utf8) and set the character encoding in options [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: String.Encoding.utf8.rawValue]Tribalism
C
1

Swift 5.1 use NSAttributedString.Key instead of NSAttributedStringKey

let test1Attributes:[NSAttributedString.Key: Any] = [.font : UIFont(name: "CircularStd-Book", size: 14)!]
let test2Attributes:[NSAttributedString.Key: Any] = [.font : UIFont(name: "CircularStd-Bold", size: 16)!]

let test1 = NSAttributedString(string: "\(greeting!) ", attributes:test1Attributes)
let test2 = NSAttributedString(string: firstName!, attributes:test2Attributes)
let text = NSMutableAttributedString()

text.append(test1)
text.append(test2)
return text
Codling answered 30/12, 2019 at 9:1 Comment(0)
I
1

for making mixed-type strings (Attributed String ) It is better to use Xcode's interface builder if the text is static. it is very easy and convenient.enter image description here

Result

Inexorable answered 2/11, 2022 at 8:15 Comment(0)
A
0

Just use code something like this:

 let font = UIFont(name: "Your-Font-Name", size: 10.0)!

        let attributedText = NSMutableAttributedString(attributedString: noteLabel.attributedText!)
        let boldedRange = NSRange(attributedText.string.range(of: "Note:")!, in: attributedText.string)
        attributedText.addAttributes([NSAttributedString.Key.font : font], range: boldedRange)
        noteLabel.attributedText = attributedText
Aureole answered 5/10, 2018 at 10:45 Comment(0)
M
0

two liner in swift 4:

            button.setAttributedTitle(.init(string: "My text", attributes: [.font: UIFont.systemFont(ofSize: 20, weight: .bold)]), for: .selected)
            button.setAttributedTitle(.init(string: "My text", attributes: [.font: UIFont.systemFont(ofSize: 20, weight: .regular)]), for: .normal)
Mckown answered 12/9, 2019 at 0:47 Comment(0)
H
0

With recent versions (iOS 15+) you can use AttributedString to create Markdown strings :

let rawMarkdown = "This is **bold**"
let content;

do {
    content = try AttributedString(markdown: rawMarkdown)
} catch {
    content = AttributedString(rawMarkdown)
}

and display them with Swift UI's Text:

Text(content)
Houri answered 19/7, 2022 at 12:28 Comment(0)
B
0

For iOS 15+ and if you want to change font also.

    do {
        let text = self.replacingOccurrences(of: "<b>", with: "**").replacingOccurrences(of: "</b>", with: "**")
        let options = AttributedString.MarkdownParsingOptions(interpretedSyntax: .inlineOnlyPreservingWhitespace)
        var attributedString = try AttributedString(markdown: text, options: options)
        attributedString.font = font
        return attributedString
    } catch {
        return AttributedString(stringLiteral: self)
    }
Bindweed answered 13/6, 2023 at 12:48 Comment(0)
R
0

For doing multiple occurrence of words to be bold in string you can use this function directly or in String extension.

 func addBoldText(text: String, substringsToBold: Array<String>, regularFont: UIFont, boldFont: UIFont) -> NSAttributedString {
    
    // Create an attributed string
    let attributedString = NSMutableAttributedString(string: text)
    // Apply regular font to the entire string
    attributedString.addAttributes([.font: regularFont], range: NSRange(location: 0, length: text.utf16.count))

    // Apply bold font to specific substrings
    for substringToBold in substringsToBold {
        var searchRange = NSRange(location: 0, length: text.utf16.count)
        while let range = text.range(of: substringToBold, options: .caseInsensitive, range: Range(searchRange, in: text)) {
            attributedString.addAttributes([.font: boldFont], range: NSRange(range, in: text))
            searchRange.location = range.upperBound.utf16Offset(in: text)
            searchRange.length = text.utf16.count - searchRange.location
        }
    }
    return attributedString
}}

And how you will be gonna use this:

 override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.

    // Create a string
    let text = "Hello, World! This is the world we live in. Welcome to the world."

    // Define font attributes for regular and bold text
    let regularFont = UIFont.italicSystemFont(ofSize: 18)
    let boldFont = UIFont.boldSystemFont(ofSize: 18)
    
    // Define an array of substrings to make bold
    let substringsToBold = ["Hello", "world", "Welcome"]

    let label = UILabel()
    label.attributedText = addBoldText(text: text, substringsToBold: substringsToBold, regularFont: regularFont, boldFont: boldFont)
    label.numberOfLines = 0
    label.frame = self.view.frame
    self.view.addSubview(label)
}

Please check a scrrenshotenter image description here

Reredos answered 9/2 at 19:27 Comment(0)
H
-1

Improving upon Prajeet Shrestha answer : -

You can make a generic extension for NSMutableAttributedString which involves less code. In this case I have chosen to use system font but you could adapt it so you can input the font name as a parameter.

    extension NSMutableAttributedString {

        func systemFontWith(text: String, size: CGFloat, weight: CGFloat) -> NSMutableAttributedString {
            let attributes: [String: AnyObject] = [NSFontAttributeName: UIFont.systemFont(ofSize: size, weight: weight)]
            let string = NSMutableAttributedString(string: text, attributes: attributes)
            self.append(string)
            return self
        }
    }
Harkey answered 4/1, 2017 at 10:10 Comment(0)
I
-1

You can do this using simple custom method written below. You have give whole string in first parameter and text to be bold in the second parameter. Hope this will help.

func getAttributedBoldString(str : String, boldTxt : String) -> NSMutableAttributedString {
        let attrStr = NSMutableAttributedString.init(string: str)
        let boldedRange = NSRange(str.range(of: boldTxt)!, in: str)
        attrStr.addAttributes([NSAttributedString.Key.font : UIFont.systemFont(ofSize: 17, weight: .bold)], range: boldedRange)
        return attrStr
    }

usage: initalString = I am a Boy

label.attributedText = getAttributedBoldString(str : initalString, boldTxt : "Boy")

resultant string = I am a Boy

Inchmeal answered 17/7, 2019 at 7:52 Comment(0)
V
-1

Swift Attributed String

The key point is to use NSMutableAttributedString to add attributes

set attributes to UILabel

let uiLabel = UILabel()
let attributedString = NSAttributedString(string: "Hello World!")
uiLabel.attributedText = attributedString

modify UILabel with attributes

let labelAttributedText = uiLabel.attributedText!
let mutableAttributedString = NSMutableAttributedString(attributedString: labelAttributedText)
let range = mutableAttributedString.mutableString.range(of: "World")
mutableAttributedString.addAttribute(.font, value: UIFont.boldSystemFont(ofSize: 21), range: range)
uiLabel.attributedText = mutableAttributedString

enter image description here

Vergievergil answered 19/8, 2023 at 13:11 Comment(0)
R
-1

For Swift 5 Xcode 15.0

you can use the following sample code:

let message = "This message should be regular.\n And this message must be Bold.\n\nAnd this one should be regular again"
let boldMessage = "And this message must be Bold."
let boldRenge = (message as NSString).range(of: boldMessage)
var attributedMessage = NSMutableAttributedString(string: message, attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 17, weight: .regular)])
attributedMessage.addAttribute(NSAttributedString.Key.font, value: UIFont.systemFont(ofSize: 17, weight: .bold), range: boldRenge)
bodyParagraphLabel.attributedText = attributedMessage

Reface answered 19/10, 2023 at 10:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.