iOS Swift: How to Change the Font Style of a Certain Word in a String

ios swift: Is it possible to change the font style of a certain word in a string?

If you already know the longest word you have to get the range of that word in the string. I prefer the NSString method rangeOfString: for this.

You then create a NSMutableAttributedString from the string, with your default attributes. Finally you apply highlighting attributes to the range you figured out earlier.

let longString = "Lorem ipsum dolor. VeryLongWord ipsum foobar"
let longestWord = "VeryLongWord"

let longestWordRange = (longString as NSString).rangeOfString(longestWord)

let attributedString = NSMutableAttributedString(string: longString, attributes: [NSFontAttributeName : UIFont.systemFontOfSize(20)])

attributedString.setAttributes([NSFontAttributeName : UIFont.boldSystemFontOfSize(20), NSForegroundColorAttributeName : UIColor.redColor()], range: longestWordRange)

label.attributedText = attributedString

Update for Swift 5.0

let longestWordRange = (longString as NSString).range(of: longestWord)

let attributedString = NSMutableAttributedString(string: longString, attributes: [NSAttributedStringKey.font : UIFont.systemFont(ofSize: 20)])

attributedString.setAttributes([NSAttributedStringKey.font : UIFont.boldSystemFont(ofSize: 20), NSAttributedStringKey.foregroundColor : UIColor.red], range: longestWordRange)

Which looks like this in my playground:

enter image description here

How do I change the font attributes of certain sections of a UILabel text in Swift?

You can use NSAttributedString to do that:

let dummy = UILabel()
let theString = "this is a String"
let attributedString = NSMutableAttributedString(string: theString, attributes: [NSFontAttributeName:UIFont.systemFontOfSize(12.0)])
let boldFontAttribute = [NSFontAttributeName: UIFont.boldSystemFontOfSize(24.0)]

attributedString.addAttributes(boldFontAttribute, range: NSMakeRange(10, theString.characters.count))

dummy.attributedText = attributedString

Change just Font of AttributedText in Swift

You first need to understand the lingo Apple uses to describe a typeface:

  • Helvetica is a family
  • Helvetica Bold, Helvetica Italic, Helvetica Bold Italic, Helvetica Display etc. are faces
  • Helvetica Bold, 12pt is a font

What you want is to replace the font family of an attributed string.

Swift 4

// Enumerate through all the font ranges
newAttributedString.enumerateAttribute(.font, in: NSMakeRange(0, newAttributedString.length), options: []) { value, range, stop in
guard let currentFont = value as? UIFont else {
return
}

// An NSFontDescriptor describes the attributes of a font: family name,
// face name, point size, etc. Here we describe the replacement font as
// coming from the "Hoefler Text" family
let fontDescriptor = currentFont.fontDescriptor.addingAttributes([.family: "Hoefler Text"])

// Ask the OS for an actual font that most closely matches the description above
if let newFontDescriptor = fontDescriptor.matchingFontDescriptors(withMandatoryKeys: [.family]).first {
let newFont = UIFont(descriptor: newFontDescriptor, size: currentFont.pointSize)
newAttributedString.addAttributes([.font: newFont], range: range)
}
}

label.attributedText = newAttributedString

Swift 3

let newAttributedString = NSMutableAttributedString(attributedString: label.attributedText)

// Enumerate through all the font ranges
newAttributedString.enumerateAttribute(NSFontAttributeName, in: NSMakeRange(0, newAttributedString.length), options: []) { value, range, stop in
guard let currentFont = value as? UIFont else {
return
}

// An NSFontDescriptor describes the attributes of a font: family name,
// face name, point size, etc. Here we describe the replacement font as
// coming from the "Hoefler Text" family
let fontDescriptor = currentFont.fontDescriptor.addingAttributes([UIFontDescriptorFamilyAttribute: "Hoefler Text"])

// Ask the OS for an actual font that most closely matches the description above
if let newFontDescriptor = fontDescriptor.matchingFontDescriptors(withMandatoryKeys: [UIFontDescriptorFamilyAttribute]).first {
let newFont = UIFont(descriptor: newFontDescriptor, size: currentFont.pointSize)
newAttributedString.addAttributes([NSFontAttributeName: newFont], range: range)
}
}

label.attributedText = newAttributedString

Original (San Francisco):

San Francisco

Replacement (Hoefler Text):

Hoefler Text

Change the style of an array of String inside a TextView - swift - EDIT

As you have changed your question, ihave updated my answer accordingly. Please try this:

extension String {

func changeAllOccurence(of strings: [String], font: UIFont) -> NSAttributedString {
let attributedString = NSMutableAttributedString(string: self)
for eachString in strings {
var range = NSMakeRange(0, attributedString.mutableString.length)

while(range.location != NSNotFound)
{
range = attributedString.mutableString.range(of: eachString, options: .caseInsensitive, range: range)
if(range.location != NSNotFound)
{
attributedString.addAttribute(NSFontAttributeName,
value: font,
range: range)
range = NSMakeRange(range.location + range.length, self.characters.count - (range.location + range.length));
}
}
}
return attributedString
}

}

I have run the code and it is working.

Swift- Change font on an HTML string that has its own Styles

The setAttributes will reset all the attributes from HTML. I wrote an extension method to avoid this:

Swift 4

public convenience init?(HTMLString html: String, font: UIFont? = nil) throws {
let options : [NSAttributedString.DocumentReadingOptionKey : Any] =
[NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html,
NSAttributedString.DocumentReadingOptionKey.characterEncoding: String.Encoding.utf8.rawValue]

guard let data = html.data(using: .utf8, allowLossyConversion: true) else {
throw NSError(domain: "Parse Error", code: 0, userInfo: nil)
}

if let font = font {
guard let attr = try? NSMutableAttributedString(data: data, options: options, documentAttributes: nil) else {
throw NSError(domain: "Parse Error", code: 0, userInfo: nil)
}
var attrs = attr.attributes(at: 0, effectiveRange: nil)
attrs[NSAttributedStringKey.font] = font
attr.setAttributes(attrs, range: NSRange(location: 0, length: attr.length))
self.init(attributedString: attr)
} else {
try? self.init(data: data, options: options, documentAttributes: nil)
}
}

Test sample:

let html = "<html><body><h1 style=\"color:red;\">html text here</h1></body></html>"
let font = UIFont.systemFont(ofSize: 16)

var attr = try NSMutableAttributedString(HTMLString: html, font: nil)
var attrs = attr?.attributes(at: 0, effectiveRange: nil)
attrs?[NSAttributedStringKey.font] as? UIFont
// print: <UICTFont: 0x7ff19fd0a530> font-family: "TimesNewRomanPS-BoldMT"; font-weight: bold; font-style: normal; font-size: 24.00pt

attr = try NSMutableAttributedString(HTMLString: html, font: font)
attrs = attr?.attributes(at: 0, effectiveRange: nil)
attrs?[NSAttributedStringKey.font] as? UIFont
// print: <UICTFont: 0x7f8c0cc04620> font-family: ".SFUIText"; font-weight: normal; font-style: normal; font-size: 16.00pt

How to set a style for a specific word inside UITextView?

How are you choosing which instance to replace?

The simplest way to do this would be to just maintain your own counter:

var counter = 0
for word in words {
if (word == selectedWord) {
counter += 1
// myTarget being the first or third or whatever
let attributesToUse = (counter == myTarget) ? selectedAttributes : normalAttributes
newText.append(NSMutableAttributedString(string: word + " " , attributes: attributesToUse as [NSAttributedString.Key : Any]))
} else {
newText.append(NSMutableAttributedString(string:word + " ", attributes: normalAttributes as [NSAttributedString.Key : Any]))
}
}

But you can certainly get cleaner by using NSAttributedStrings and looking for the range of your text..

let myText = NSMutableAttributedString(string: textView.text, attributes: normalAttributes)

// this will only turn up the FIRST occurrence
if let range = myText.range(of: selectedWord) {
let rangeOfSelected = NSRange(range, in: myText)
myText.setAttributes(selectedAttributes, range: rangeOfSelected)
}

If you want to use arbitrary occurrence you can prob write an extension that creates an array of all the ranges and then pick the one that matters, this is a good reference for that: https://medium.com/@weijentu/find-and-return-the-ranges-of-all-the-occurrences-of-a-given-string-in-swift-2a2015907a0e

Def could be overkill though, you can also modify the methods in those article to instead to take in an int (occuranceNumber) and use a counter like above to return only the range of the nth occurrence, and then do the same thing with attributed strings.

How can I change style of some words in my UITextView one by one in Swift?

Use a timer. Stash matches in a property. Stash the base unhighlighted attributed string in a property. Now have your timer highlight the first match and call itself again in 1 second, highlighting up to the second match and repeat until there are no matches left.

    func highlight (to index: Int = 0) {
guard index < matches.count else {
return
}
let titleDict: NSDictionary = [NSForegroundColorAttributeName: orangeColor]
let attributedString = NSMutableAttributedString(attributedString: storedAttributedString)
for i in 0..< index {
let matchRange = matches[i].rangeAt(0)
attributedString.addAttributes(titleDict as! [String : AnyObject], range: matchRange)
}
self.attributedText = attributedString
let _ = Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { _ in
self.highlight(to: index + 1)
}
}

Swift - Changing font size inside label

Look at the API for NSAttributedString -- it allows you to create a string that specifies portions of the string that should be styled with specific text styles and/or fonts. The resulting object can be used instead of a plain string with UILabel (and other UI elements) by setting the label's attributedText property instead of the usual text property.

To make just the word "bold" appear in 18 point bold, try something like the following:

var label = UILabel()
let bigBoldFont = UIFont.boldSystemFontOfSize(18.0)

var attrString = NSMutableAttributedString(string: "This text is bold.")
attrString.addAttribute(kCTFontAttributeName, value: bigBoldFont, range: NSMakeRange(13, 4))

label.attributedText = attrString

The range specified determines the portion of the string to which the named attributed (in this case, the font) should be applied. And note that the parameters to NSMakeRange are the starting character position and the length of the range.



Related Topics



Leave a reply



Submit