Add text with different style to a existing label - ios

I have a label with text and want to add more test in running time, but I want to add different style to this text that was add. Is there a way to do this?
This is the code
label.text = (label.text ?? "") + " \n \(userName)"
How do I add style to userName without changing the style of the label?

use attributed text in UILabel:
here some code.
a) some useful typedefs:
typealias AttrDict = [NSAttributedString.Key : Any]
a) create some styles:
func textAttribute() -> AttrDict{
let textFont = UIFont.systemFont(ofSize: 32)
let stdAttrib = [NSAttributedString.Key.font: textFont,
//NSParagraphStyleAttributeName: paragraphStyle2,
NSAttributedString.Key.foregroundColor: UIColor.red] as AttrDict
return stdAttrib
}
func smallTextAttribute() -> AttrDict{
let textFont = UIFont.systemFont(ofSize: 10)
let stdAttrib = [NSAttributedString.Key.font: textFont,
NSAttributedString.Key.foregroundColor: UIColor.green] as AttrDict
return stdAttrib
}
c) build Your attributed String:
func myAttributedString() -> NSAttributedString {
let pieces = ["hello", "word"]
let resultAttributed = NSMutableAttributedString()
var s = ""
s = pieces[0] + "\n"
resultAttributed.append(NSAttributedString(string: s,
attributes: stdTextAttribute() ))
s = pieces[1] + "\n"
resultAttributed.append(NSAttributedString(string: s,
attributes: smallTextAttribute() ))
return resultAttributed
}
d) put in Your label/textView:
....
class ViewController: UIViewController {
#IBOutlet weak var myLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
myLabel.numberOfLines = 0
myLabel.attributedText = myAttributedString()
}
}
I made a GIST:
https://gist.github.com/ingconti/aefc78c6d0b22f5329f906094c312a21
PLS connect UIlabel..
:)

To do this, you need to use NSMutableAttributedString, NSAttributedString and use label.attributedText, How?
Doing this:
let userName = "StackOverflow"
let prefixText = NSAttributedString(string: "this is normal ")
let font = UIFont.systemFont(ofSize: 40)
let attributes: [NSAttributedString.Key: Any] = [
.font: font,
.foregroundColor: UIColor.blue
]
let userNameWithStyle = NSAttributedString(string: userName, attributes: attributes)
let finalString = NSMutableAttributedString(attributedString: prefixText)
finalString.append(userNameWithStyle)
self.label.attributedText = finalString
Image result

Related

One string with multiple paragraph styles

I want to have one string with different paragraphs styles. The goal is to customize the paragraph/line spacing for different parts of the string. I researched and found this answer but since I added multiple new line characters, not sure how to implement.
Design
This is my goal in terms of layout:
Code
This is the code I have which makes it look like the left image above. Please see the comments Not working in the code. Notice how the spacing is set for the main string, but the other strings can't then set their own custom spacing:
struct BookModel: Codable {
let main: String
let detail: String
}
func createAttributedString(for model: BookModel) -> NSMutableAttributedString {
let fullString = NSMutableAttributedString()
let mainString = NSMutableAttributedString(string: model.main)
let mainStringParagraphStyle = NSMutableParagraphStyle()
mainStringParagraphStyle.alignment = .center
mainStringParagraphStyle.lineSpacing = 10
mainStringParagraphStyle.paragraphSpacing = 30
let mainStringAttributes: [NSAttributedString.Key: Any] = [.paragraphStyle: mainStringParagraphStyle]
let spacingAfterQuote = NSMutableAttributedString(string: "\n")
let lineImageAttachment = NSTextAttachment(image: #imageLiteral(resourceName: "line-image"))
let lineImageString = NSMutableAttributedString(attachment: lineImageAttachment)
let lineParagraphStyle = NSMutableParagraphStyle()
lineParagraphStyle.alignment = .left
lineParagraphStyle.lineSpacing = 0 // Not working - instead of 0 it is 30 from `mainStringParagraphStyle`
lineParagraphStyle.paragraphSpacing = 0 // Not working - instead of 0 it is 30 from `mainStringParagraphStyle`
let lineAttributes: [NSAttributedString.Key: Any] = [.paragraphStyle: lineParagraphStyle]
let spacingAfterSeparator = NSMutableAttributedString(string: "\n")
let spacingAfterSeparatorParagraphStyle = NSMutableParagraphStyle()
spacingAfterSeparatorParagraphStyle.alignment = .left
spacingAfterSeparatorParagraphStyle.lineSpacing = 0 // Not working - instead of 0 it is 30 from `mainStringParagraphStyle`
spacingAfterSeparatorParagraphStyle.paragraphSpacing = 5 // Not working - instead of 5 it is 30 from `mainStringParagraphStyle`
let spacingAfterSeparatorAttributes: [NSAttributedString.Key: Any] = [.paragraphStyle: spacingAfterSeparatorParagraphStyle]
let detailString = NSMutableAttributedString(string: model.detail)
let detailStringAttributes: [NSAttributedString.Key: Any] = [.font: UIFont.systemFont(ofSize: 20)]
fullString.append(mainString)
fullString.append(spacingAfterQuote)
fullString.append(lineImageString)
fullString.append(spacingAfterSeparator)
fullString.append(detailString)
fullString.addAttributes(mainStringAttributes, range: fullString.mutableString.range(of: model.main))
fullString.addAttributes(lineAttributes, range: fullString.mutableString.range(of: lineImageString.string))
fullString.addAttributes(spacingAfterSeparatorAttributes, range: fullString.mutableString.range(of: spacingAfterSeparator.string))
fullString.addAttributes(detailStringAttributes, range: fullString.mutableString.range(of: model.detail))
return fullString
}
Any thoughts on how to achieve the image on the right?
Question Update 1
The code below is working! There is only one slight problem. When I add lineSpacing, there is extra space at the end of the last line in main string. Notice that I have this set to zero: mainStringParagraphStyle.paragraphSpacing = 0, but there is still space at the end because mainStringParagraphStyle.lineSpacing = 60.
The reason I ask this is to have more fine grain control of spacing. For example, have a perfect number between the line image and main string. Any thoughts on this?
I put code and picture below:
Code:
func createAttributedString(for model: BookModel) -> NSMutableAttributedString {
let fullString = NSMutableAttributedString()
let mainStringParagraphStyle = NSMutableParagraphStyle()
mainStringParagraphStyle.alignment = .center
mainStringParagraphStyle.paragraphSpacing = 0 // The space after the end of the paragraph
mainStringParagraphStyle.lineSpacing = 60 // NOTE: This controls the spacing after the last line instead of just `paragraphSpacing`
let mainString = NSAttributedString(string: "\(model.main)\n",
attributes: [.paragraphStyle: mainStringParagraphStyle, .font: UIFont.systemFont(ofSize: 24)])
let lineImageStringParagraphStyle = NSMutableParagraphStyle()
lineImageStringParagraphStyle.alignment = .center
let lineImageAttachment = NSTextAttachment(image: #imageLiteral(resourceName: "line-view"))
let lineImageString = NSMutableAttributedString(attachment: lineImageAttachment)
lineImageString.addAttribute(.paragraphStyle, value: lineImageStringParagraphStyle, range: NSRange(location: 0, length: lineImageString.length))
let detailStringParagraphStyle = NSMutableParagraphStyle()
detailStringParagraphStyle.alignment = .center
detailStringParagraphStyle.paragraphSpacingBefore = 5 // The distance between the paragraph’s top and the beginning of its text content
detailStringParagraphStyle.lineSpacing = 0
let detailString = NSAttributedString(string: "\n\(model.detail)",
attributes: [.paragraphStyle: detailStringParagraphStyle, .font: UIFont.systemFont(ofSize: 12)])
fullString.append(mainString)
fullString.append(lineImageString)
fullString.append(detailString)
return fullString
}
Updated answer:
Here's a new example. I set the spacing at the top and at the bottom of the paragraph with the image. This allows line breaks to be used in model.main and model.detail if needed. Also, instead of lineSpacing, I used lineHeightMultiple. This parameter affects the indentation between lines without affecting the last line:
func createAttributedString(for model: BookModel) -> NSAttributedString {
let fullString = NSMutableAttributedString()
let mainStringParagraphStyle = NSMutableParagraphStyle()
mainStringParagraphStyle.alignment = .center
mainStringParagraphStyle.lineHeightMultiple = 2 // Note that this is a multiplier, not a value in points
let mainString = NSAttributedString(string: "\(model.main)\n", attributes: [.paragraphStyle: mainStringParagraphStyle, .font: UIFont.systemFont(ofSize: 24)])
let lineImageStringParagraphStyle = NSMutableParagraphStyle()
lineImageStringParagraphStyle.alignment = .center
lineImageStringParagraphStyle.paragraphSpacingBefore = 10 // The space before image
lineImageStringParagraphStyle.paragraphSpacing = 20 // The space after image
let lineImageAttachment = NSTextAttachment(image: #imageLiteral(resourceName: "line-image"))
let lineImageString = NSMutableAttributedString(attachment: lineImageAttachment)
lineImageString.addAttribute(.paragraphStyle, value: lineImageStringParagraphStyle, range: NSRange(location: 0, length: lineImageString.length))
let detailStringParagraphStyle = NSMutableParagraphStyle()
detailStringParagraphStyle.alignment = .center
let detailString = NSAttributedString(string: "\n\(model.detail)", attributes: [.paragraphStyle: detailStringParagraphStyle, .font: UIFont.systemFont(ofSize: 12)])
fullString.append(mainString)
fullString.append(lineImageString)
fullString.append(detailString)
return fullString
}
Also have a look at my library StringEx. It allows you to create a NSAttributedString from the template and apply styles without having to write a ton of code:
import StringEx
...
func createAttributedString(for model: BookModel) -> NSAttributedString {
let pattern = "<main />\n<image />\n<detail />"
let ex = pattern.ex
ex[.tag("main")]
.insert(model.main)
.style([
.aligment(.center),
.lineHeightMultiple(2),
.font(.systemFont(ofSize: 24))
])
let lineImageAttachment = NSTextAttachment(image: #imageLiteral(resourceName: "line-image"))
let lineImageString = NSAttributedString(attachment: lineImageAttachment)
ex[.tag("image")]
.insert(lineImageString)
.style([
.aligment(.center),
.paragraphSpacingBefore(10),
.paragraphSpacing(20)
])
ex[.tag("detail")]
.insert(model.detail)
.style([
.aligment(.center),
.font(.systemFont(ofSize: 12))
])
return ex.attributedString
}
Old answer:
I think you can just set the spacing at the end of the first paragraph (main string) and the spacing at the beginning of the last paragraph (detail string):
func createAttributedString(for model: BookModel) -> NSMutableAttributedString {
let fullString = NSMutableAttributedString()
let mainStringParagraphStyle = NSMutableParagraphStyle()
mainStringParagraphStyle.alignment = .center
mainStringParagraphStyle.paragraphSpacing = 30 // The space after the end of the paragraph
let mainString = NSAttributedString(string: "\(model.main)\n", attributes: [.paragraphStyle: mainStringParagraphStyle])
let lineImageStringParagraphStyle = NSMutableParagraphStyle()
lineImageStringParagraphStyle.alignment = .center
let lineImageAttachment = NSTextAttachment(image: #imageLiteral(resourceName: "line-image"))
let lineImageString = NSMutableAttributedString(attachment: lineImageAttachment)
lineImageString.addAttribute(.paragraphStyle, value: lineImageStringParagraphStyle, range: NSRange(location: 0, length: lineImageString.length))
let detailStringParagraphStyle = NSMutableParagraphStyle()
detailStringParagraphStyle.alignment = .center
detailStringParagraphStyle.paragraphSpacingBefore = 5 // The distance between the paragraph’s top and the beginning of its text content
let detailString = NSAttributedString(string: "\n\(model.detail)", attributes: [.paragraphStyle: detailStringParagraphStyle])
fullString.append(mainString)
fullString.append(lineImageString)
fullString.append(detailString)
return fullString
}

UILabel.attributedText set attributes once and then just change text (string)

How to set UILabel text attributes only once and then just change text (string)
mTextValue.attributedText = NSAttributedString(string: "STRING",
attributes:
[NSAttributedStringKey.strokeWidth: -3.0,
NSAttributedStringKey.strokeColor: UIColor.black])
mTextValue.text = "NEW STRING" // won't change anything
or to set new string do I have to set NSAttributedString to .attributedText again and again?
You could declare a mutableAttributed string separat and change the string of it like here:
let yourString = "my string"
let yourAttributes = [NSAttributedStringKey.strokeWidth: -3.0, NSAttributedStringKey.strokeColor: UIColor.black] as [NSAttributedStringKey : Any]
let mutableAttributedString = NSMutableAttributedString(string: yourString, attributes: yourAttributes)
let yourNewString = "my new string"
mutableAttributedString.mutableString.setString(yourNewString)
Full example:
import UIKit
class ViewController: UIViewController {
var mutableAttributedString = NSMutableAttributedString()
#IBAction func buttonTapped(_ sender: Any) {
mutableAttributedString.mutableString.setString("new string")
mainLabel.attributedText = mutableAttributedString
}
#IBOutlet weak var mainLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let yourString = "my string"
let yourAttributes = [NSAttributedStringKey.strokeWidth: -3.0, NSAttributedStringKey.strokeColor: UIColor.blue] as [NSAttributedStringKey : Any]
mutableAttributedString = NSMutableAttributedString(string: yourString, attributes: yourAttributes)
mainLabel.attributedText = mutableAttributedString
}
}

make part of the text bold in a UITextField

Based on the answers here I made this code:
extension NSMutableAttributedString {
func bold(text:String, size:CGFloat) -> NSMutableAttributedString {
let attrs:[String:AnyObject] = [NSFontAttributeName : UIFont.boldSystemFontOfSize(size)]
let boldString = NSMutableAttributedString(string:"\(text)", attributes:attrs)
self.appendAttributedString(boldString)
return self
}
func normal(text:String)->NSMutableAttributedString {
let normal = NSAttributedString(string: text)
self.appendAttributedString(normal)
return self
}
}
and I use it like this:
#IBOutlet weak var m_field: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
let string = NSMutableAttributedString()
string.bold("Bold_text: ",size: 12).normal("normal text")
m_field.attributedText = string
}
but it doesn't work, all my text is the same (bold I think)
what am I doing wrong?
Enjoy - below code works for swift 3
let normalText = "Hi am normal"
let boldText = "And I am BOLD!"
let attributedString = NSMutableAttributedString(string:normalText)
let attrs = [NSFontAttributeName : UIFont.boldSystemFont(ofSize: 15)]
let boldString = NSMutableAttributedString(string:boldText, attributes:attrs)
attributedString.append(boldString)
txt.attributedText = attributedString
where txt is TextField outlet
assign "**string**" variable value to **attributedText** property
var m_field = UITextField()
m_field.frame = CGRect(x: 0, y: 66, width: 400, height: 100)
let string = NSMutableAttributedString()
string.bold("Bold_text: ",size: 15).normal("normal text")
m_field.attributedText = string
self.view .addSubview(m_field)

Swift Attributed Title Syntax

I'm trying to do something like this:
let introText = "This is sample "
let facebookText = "Text"
loginButton.setTitle("\(introText)\(facebookText)", forState: .Normal)
loginButton.addAttribute(NSFontAttributeName, value: UIFont(name: "Arial", size: 15.5)!, range: NSMakeRange(0, introText.characters.count))
loginButton.addAttribute(NSFontAttributeName, value: UIFont(name: "Arial-Bold", size: 15.5)!, range: NSMakeRange(introText.characters.count, facebookText.characters.count))
loginButton.addAttribute(NSForegroundColorAttributeName, value: UIColor.whiteColor(), range: NSMakeRange(0, introText.characters.count + facebookText.characters.count))
in this form:
loginButton.setAttributedTitle(NSMutableAttributedString(
string: "\(introText)\(facebookText)",
attributes: [
// attributes go here
NSForegroundColorAttributeName: UIColor.colorFromCode(0x151515),
]), forState: UIControlState.Normal)
Is it possible for me to do this? I'm having trouble figuring out how to include the range on included attributes.
EDIT
Sorry if it wasn't obvious, but what my code does is it creates an attributed string that reads "This is sample Text" with the word Text bolded as shown. I'm trying to rewrite this code to be in the form of the second syntax I'm showing, if it's even possible.
Thanks!
If you are looking for an attributed text with bolded part, this will do it for you.
extension String {
func getPartOfStringBold(boldPart:String)-> NSAttributedString{
return getPartOfStringBold(boldPart, font: UIFont(name: "Taz-Bold", size: 13)!)
}
//Make your string bold
func getPartOfStringBold(boldPart:String, font:UIFont)-> NSAttributedString{
let attributtedString = NSMutableAttributedString(string: self)
let attrs = [NSFontAttributeName:font]
let rangePart: NSRange = (attributtedString.string as NSString).rangeOfString(boldPart)
attributtedString.addAttributes(attrs, range: rangePart)
return attributtedString
}
//Make your string Italic
func getPartOfStringItalic(italicPart:String)-> NSAttributedString{
let attributtedString = NSMutableAttributedString(string: self)
if let font = UIFont(name: "Taz-LightItalic", size: 13)
{
let attrs = [NSFontAttributeName:font, NSForegroundColorAttributeName:UIColor.blackColor()]
let rangePart: NSRange = (attributtedString.string as NSString).rangeOfString(italicPart)
attributtedString.addAttributes(attrs, range: rangePart)
}
return attributtedString
}
}
as far as I have understood your problem, you want to make a portion of test as bold if yes then here is an extension which I am using for this purpose
import UIKit
import Foundation
extension String
{
static func makeTextBold(preBoldText:String, boldText:String, postBoldText:String, fontSzie:CGFloat) -> NSAttributedString {
let boldAttrs = [NSFontAttributeName : UIFont(name: "HelveticaNeue-Bold", size: fontSzie) as? AnyObject]
let attributedString = NSMutableAttributedString(string:boldText, attributes:boldAttrs as? [String:AnyObject])
let lightAttr = [NSFontAttributeName : UIFont(name: "HelveticaNeue-Light", size: fontSzie) as? AnyObject]
let finalAttributedText = NSMutableAttributedString(string:preBoldText, attributes:lightAttr as? [String:AnyObject])
let postText = NSMutableAttributedString(string:postBoldText, attributes:lightAttr as? [String:AnyObject])
finalAttributedText.appendAttributedString(attributedString)
finalAttributedText.appendAttributedString(postText)
// print(finalAttributedText)
return finalAttributedText
}
}
So basically what this function is doing is that you pass three parameters for text and one for fot size and it will return an attributed string.
Here is an example usage for your case
myLabel.attributedText = String.makeTextBold("This is sample", boldText: "Text", postBoldText: "", fontSzie: 21)
the output would be
This is sample Text
I hope this answer the question :-)

Making text bold using attributed string in swift

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.
Usage:
let label = UILabel()
label.attributedText =
NSMutableAttributedString()
.bold("Address: ")
.normal(" Kathmandu, Nepal\n\n")
.orangeHighlight(" Email: ")
.blackHighlight(" prajeet.shrestha#gmail.com ")
.bold("\n\nCopyright: ")
.underlined(" All rights reserved. 2020.")
Result:
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.
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
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:
DiscussionThe 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
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
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
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)
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)
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"
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)
}
}
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
}
}
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
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
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
}
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)!
}
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
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.
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
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)
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)
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
}
}
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

Resources