How to Use Nsattributedstring

How to use Attributed String in SwiftUI

iOS 15 and Swift 5.5

Text now supports markdown and also you can create custom attributes:

Sample Image

You can even get defined attributes remotely like:

Sample Image



iOS 13 and 14

You can combine multiple Text objects together with a simple + operator and that will handle some of the attributions:

Sample Image

Each one can have multiple and specific modifiers



A fully supported fallback!

Since it doesn't support directly on Text (till iOS 15), you can bring the UILabel there and modify it in anyway you like:

Implementation:

struct UIKLabel: UIViewRepresentable {

typealias TheUIView = UILabel
fileprivate var configuration = { (view: TheUIView) in }

func makeUIView(context: UIViewRepresentableContext<Self>) -> TheUIView { TheUIView() }
func updateUIView(_ uiView: TheUIView, context: UIViewRepresentableContext<Self>) {
configuration(uiView)
}
}

Usage:

var body: some View {
UIKLabel {
$0.attributedText = NSAttributedString(string: "HelloWorld")
}
}

How to use an NSAttributedString with a ScrollView in SwiftUI?

The reason is that SwiftUI ScrollView requires defined content size, but used UITextView is itself a UIScrollView and detects content based on available space in parent view. Thus it happens cycle of undefined sizes.

Here is a simplified demo of possible approach how to solve this. The idea is to calculate content size of UITextView and pass it to SwiftUI...

struct TextWithAttributedString: UIViewRepresentable {
@Binding var height: CGFloat
var attributedString: NSAttributedString

func makeUIView(context: Context) -> UITextView {
let textView = UITextView(frame: .zero)
textView.isEditable = false
return textView
}

func updateUIView(_ textView: UITextView, context: Context) {
textView.attributedText = self.attributedString

// calculate height based on main screen, but this might be
// improved for more generic cases
DispatchQueue.main.async { // << fixed
height = textView.sizeThatFits(UIScreen.main.bounds.size).height
}
}
}


struct NSAttributedStringView: View {
@State private var textHeight: CGFloat = .zero
var body: some View {
ScrollView {
TextWithAttributedString(height: $textHeight, attributedString: NSAttributedString(string: exampleText))
.frame(height: textHeight) // << specify height explicitly !
}
}
}

backup

How do you use NSAttributedString?

When building attributed strings, I prefer to use the mutable subclass, just to keep things cleaner.

That being said, here's how you create a tri-color attributed string:

NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:@"firstsecondthird"];
[string addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0,5)];
[string addAttribute:NSForegroundColorAttributeName value:[UIColor greenColor] range:NSMakeRange(5,6)];
[string addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:NSMakeRange(11,5)];

typed in a browser. caveat implementor

Obviously you're not going to hard-code in the ranges like this. Perhaps instead you could do something like:

NSDictionary *wordToColorMapping = ....;  //an NSDictionary of NSString => UIColor pairs
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:@""];
for (NSString *word in wordToColorMapping) {
UIColor *color = [wordToColorMapping objectForKey:word];
NSDictionary *attributes = [NSDictionary dictionaryWithObject:color forKey:NSForegroundColorAttributeName];
NSAttributedString *subString = [[NSAttributedString alloc] initWithString:word attributes:attributes];
[string appendAttributedString:subString];
[subString release];
}

//display string

how to append Attributed Text String with Attributed String in Swift

Use NSMutableAttributedString to achieve that.

Example

Swift 5

let yourAttributes = [NSAttributedString.Key.foregroundColor: UIColor.black, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 15)]
let yourOtherAttributes = [NSAttributedString.Key.foregroundColor: UIColor.red, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 25)]

let partOne = NSMutableAttributedString(string: "This is an example ", attributes: yourAttributes)
let partTwo = NSMutableAttributedString(string: "for the combination of Attributed String!", attributes: yourOtherAttributes)

partOne.append(partTwo)

Swift 3

let yourAttributes = [NSForegroundColorAttributeName: UIColor.black, NSFontAttributeName: UIFont.systemFont(ofSize: 15)]
let yourOtherAttributes = [NSForegroundColorAttributeName: UIColor.red, NSFontAttributeName: UIFont.systemFont(ofSize: 25)]

let partOne = NSMutableAttributedString(string: "This is an example ", attributes: yourAttributes)
let partTwo = NSMutableAttributedString(string: "for the combination of Attributed String!", attributes: yourOtherAttributes)

let combination = NSMutableAttributedString()

combination.append(partOne)
combination.append(partTwo)

combination represents your final string which contains both formattings provided by yourAttributes and yourOtherAttributes

Even older

let yourAttributes = [NSForegroundColorAttributeName: UIColor.blackColor(), NSFontAttributeName: UIFont.systemFontOfSize(15)]
let yourOtherAttributes = [NSForegroundColorAttributeName: UIColor.redColor(), NSFontAttributeName: UIFont.systemFontOfSize(25)]

let partOne = NSMutableAttributedString(string: "This is an example ", attributes: yourAttributes)
let partTwo = NSMutableAttributedString(string: "for the combination of Attributed String!", attributes: yourOtherAttributes)

let combination = NSMutableAttributedString()

combination.appendAttributedString(partOne)
combination.appendAttributedString(partTwo)

iphone/ipad: How exactly use NSAttributedString?

You should take a look at AliSoftware's OHAttributedLabel. It is a subclass of UILabel that draws an NSAttributedString and also provides convenience methods for setting the attributes of an NSAttributedString from UIKit classes.

From the sample provided in the repo:

#import "NSAttributedString+Attributes.h"
#import "OHAttributedLabel.h"

/**(1)** Build the NSAttributedString *******/
NSMutableAttributedString* attrStr = [NSMutableAttributedString attributedStringWithString:@"Hello World!"];
// for those calls we don't specify a range so it affects the whole string
[attrStr setFont:[UIFont systemFontOfSize:12]];
[attrStr setTextColor:[UIColor grayColor]];
// now we only change the color of "Hello"
[attrStr setTextColor:[UIColor redColor] range:NSMakeRange(0,5)];


/**(2)** Affect the NSAttributedString to the OHAttributedLabel *******/
myAttributedLabel.attributedText = attrStr;
// Use the "Justified" alignment
myAttributedLabel.textAlignment = UITextAlignmentJustify;
// "Hello World!" will be displayed in the label, justified, "Hello" in red and " World!" in gray.

Note: In iOS 6+ you can render attributed strings using the attributedText property of UILabel.

How to use replacingOccurrences for NSAttributedString in swift?

To get this working,

1. First you need to find the indices of all the duplicate substrings existing in a string. To get that you can use this: https://stackoverflow.com/a/40413665/5716829

extension String {
func indicesOf(string: String) -> [Int] {
var indices = [Int]()
var searchStartIndex = self.startIndex

while searchStartIndex < self.endIndex,
let range = self.range(of: string, range: searchStartIndex..<self.endIndex),
!range.isEmpty
{
let index = distance(from: self.startIndex, to: range.lowerBound)
indices.append(index)
searchStartIndex = range.upperBound
}

return indices
}
}

2. Next you need to apply your desired attribute to substring at each index, i.e.

    let str = "The problem is that replacingOccurrences Hello is only possible for string types, as I want to give Hello a new value every time Hello the word appears in the entire sentence Hello."
let indices = str.indicesOf(string: "Hello")
let attrStr = NSMutableAttributedString(string: str, attributes: [.foregroundColor : UIColor.blue])
for index in indices
{
//You can write your own logic to specify the color for each duplicate. I have used some hardcode indices
var color: UIColor
switch index
{
case 41:
color = .orange
case 100:
color = .magenta
case 129:
color = .green
default:
color = .red
}
attrStr.addAttribute(.foregroundColor, value: color, range: NSRange(location: index, length: "Hello".count))
}

Screenshot:

Sample Image

Let me know if you still face any issues. Happy Coding../p>

How to set font size on NSAttributedString

let myString = "Swift Attributed String"
let myAttribute = [ NSForegroundColorAttributeName: UIColor.blue ]
let myAttrString = NSAttributedString(string: myString, attributes: myAttribute)

// set attributed text on a UILabel
myLabel.attributedText = myAttrString

Font

let myAttribute = [ NSFontAttributeName: UIFont(name: "Chalkduster", size: 18.0)! ]

Shadow

let myShadow = NSShadow()
myShadow.shadowBlurRadius = 3
myShadow.shadowOffset = CGSize(width: 3, height: 3)
myShadow.shadowColor = UIColor.gray
let myAttribute = [ NSShadowAttributeName: myShadow ]

Underline

let myAttribute = [ NSUnderlineStyleAttributeName: NSUnderlineStyle.StyleSingle.rawValue ]

Textcolor

let myAttribute = [ NSForegroundColorAttributeName: UIColor.blue ]

Background Color

let myAttribute = [ NSBackgroundColorAttributeName: UIColor.yellow ]

NSAttributedString: How to mimic opacity or alpha equivalent using color

You can change any color alpha using

UIColor.red.withAlphaComponent(0.5)

Of course, you have to know the original color.

There is no universal alpha modifier.

IOS Anyway to have NSAttributedString throughout app. Swift

Based on @AdamPro13 suggestion, you could create a protocol extension for your NSAttributedString:

So, create NSAttributedStringExtension.swift with something like that:

protocol NSAttributedStringExtension {
static func attributed(string:String, font:UIFont, color:UIColor) -> NSAttributedString
}

extension NSAttributedString : NSAttributedStringExtension {
class func attributed(string:String, font:UIFont, color:UIColor) -> NSAttributedString {

let attrs = [NSFontAttributeName:font, NSForegroundColorAttributeName:color]
return NSAttributedString(string: string, attributes: attrs)
}
}

And you could make several different functions for different label types.
Just apply then on your label (rough code):

let label:UILabel
let font:UIFont
let color:UIColor
label.attributedText = NSAttributedString.attributed("test", font: font, color: color)

Note: the font and colour you could setup in your protocol extension function



Related Topics



Leave a reply



Submit