Cross strikethrough text in swift - swift

I need Strikethrough text in swift, I have done this with NSMutableAttributedString but strike shows horizontally. But I need that cross like
My code:
let attributeString: NSMutableAttributedString = NSMutableAttributedString(string: textLabel.text!)
attributeString.addAttribute(NSStrikethroughStyleAttributeName, value: 1, range: NSMakeRange(0, attributeString.length))
attributeString.addAttribute(NSStrikethroughColorAttributeName, value: colors.kSkyColor, range: NSMakeRange(0, attributeString.length))
textLabel.attributedText = attributeString

Related

Multiple Hyperlinks in UITextView : Underlined and Bold, Bold Not working

I have this code from a post on SO, I cannot find the original link, so I do deeply apologize.
Essentially, this code works for everything I need to do in a UITextView, multiple links with underline. However, when I try to add the Bold attribute, I am unable to get that to work.
import UIKit
extension UITextView {
func buildLink(originalText: String, hyperLinks: [String: String]) {
let style = NSMutableParagraphStyle()
style.alignment = .left
let attributedOriginalText = NSMutableAttributedString(string: originalText)
for (hyperLink, urlString) in hyperLinks {
let linkRange = attributedOriginalText.mutableString.range(of: hyperLink)
let fullRange = NSRange(location: 0, length: attributedOriginalText.length)
attributedOriginalText.addAttribute(.font, value: UIFont(name: "RobotoCondensed-Bold", size: 12.0)!, range: linkRange) /// this is the non functioning line
attributedOriginalText.addAttribute(NSAttributedString.Key.link, value: urlString, range: linkRange)
attributedOriginalText.addAttribute(NSAttributedString.Key.paragraphStyle, value: style, range: fullRange)
attributedOriginalText.addAttribute(NSAttributedString.Key.font, value: UIFont(name: "RobotoCondensed-Regular", size 12.0)!, range: fullRange)
attributedOriginalText.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.darkText, range: fullRange)
}
self.linkTextAttributes = [
NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue
]
self.attributedText = attributedOriginalText
}
}
If I also put the bold attribute in the linkTextAttributes array, it also doesn't work.
scratching my head on this.
The problem is that you are applying the regular (NOT BOLD) text style to fullRange AFTER the bold has been applied to the linkRange.
for (hyperLink, urlString) in hyperLinks {
let linkRange = attributedOriginalText.mutableString.range(of: hyperLink)
let fullRange = NSRange(location: 0, length: attributedOriginalText.length)
/// Here the correct attribute is applied for linkRange
attributedOriginalText.addAttribute(.font, value: UIFont(name: "RobotoCondensed-Bold", size: 12.0)!, range: linkRange) /// this is the non functioning line
attributedOriginalText.addAttribute(NSAttributedString.Key.link, value: urlString, range: linkRange)
attributedOriginalText.addAttribute(NSAttributedString.Key.paragraphStyle, value: style, range: fullRange)
/// Here what was done correctly above gets overwritten
attributedOriginalText.addAttribute(NSAttributedString.Key.font, value: UIFont(name: "RobotoCondensed-Regular", size 12.0)!, range: fullRange)
attributedOriginalText.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.darkText, range: fullRange)
}
This can be simplified to following -
let attributedOriginalText = NSMutableAttributedString(string: originalText)
/// Apply the normal text style to whole string at once
let fullRange = NSRange(location: 0, length: attributedOriginalText.length)
attributedOriginalText.addAttribute(.paragraphStyle, value: style, range: fullRange)
attributedOriginalText.addAttribute(.font, value: UIFont(name: "RobotoCondensed-Regular", size 12.0)!, range: fullRange)
attributedOriginalText.addAttribute(.foregroundColor, value: UIColor.darkText, range: fullRange)
/// Apply the link attributes at specified link ranges
for (hyperLink, urlString) in hyperLinks {
let linkRange = attributedOriginalText.mutableString.range(of: hyperLink)
attributedOriginalText.addAttribute(.font, value: UIFont(name: "RobotoCondensed-Bold", size: 12.0)!, range: linkRange)
attributedOriginalText.addAttribute(.link, value: urlString, range: linkRange)
}

TextView Delegate Method Not Being Called

All of my code except for the delegate method is working fine (I added the extra code for context) but you can ignore that if you want and focus on the ifs/else ifs and the delegate method.
The delegate method is supposed to be called when a link is clicked (the link and link attribute are working well) but the delegate method is not being called for some reason. Can someone please tell me why and what I need to do to fix it.
let words = formulaTextView.text
let split = words?.split(separator: " ")
let last2words = String((split?.suffix(2).joined(separator: " "))!)
let first2words = String((split?.prefix(2).joined(separator: " "))!)
let firstWord = String((split?.prefix(1).joined(separator: " "))!)
let lastWord = String((split?.suffix(1).joined(separator: " "))!)
let first3Words = String((split?.prefix(3).joined(separator: " "))!)
let last3Words = String((split?.suffix(3).joined(separator: " "))!)
let listOfWords = [first2words,last2words,lastWord,firstWord,last3Words,first3Words]
formulaTextView.text = "Formula: \(words!)"
var y: NSMutableAttributedString?
for k in listOfWords {
if termStrings.contains(k) {
if words!.contains(k) && y == nil {
let textViewAttributedString = NSMutableAttributedString(string: formulaTextView.text!)
textViewAttributedString.addAttribute(.font, value: UIFont(name: "Arial", size: 14.0)!, range: NSMakeRange(0, textViewAttributedString.length))
let attributedString = NSMutableAttributedString(string: k)
attributedString.addAttribute(.font, value: UIFont(name: "Arial", size: 14.0)!, range: NSMakeRange(0, attributedString.length))
attributedString.addAttribute(.underlineStyle, value: 1, range: NSMakeRange(0, attributedString.length))
attributedString.addAttribute(.underlineColor, value: UIColor.link, range: NSMakeRange(0, attributedString.length))
attributedString.addAttribute(.foregroundColor, value: UIColor.link, range: NSMakeRange(0, attributedString.length))
attributedString.addAttribute(.link, value: k, range: NSMakeRange(0, attributedString.length))
formulaTextView.linkTextAttributes = [.foregroundColor: UIColor.link, .font: UIFont(name: "Arial", size: 14.0)!]
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .left
let range = textViewAttributedString.string.range(of: k)!
let nsrange = NSRange(range, in: textViewAttributedString.string)
textViewAttributedString.replaceCharacters(in: nsrange, with: attributedString)
y = textViewAttributedString
textViewAttributedString.addAttribute(.paragraphStyle, value: paragraphStyle, range: NSMakeRange(0, textViewAttributedString.length))
formulaTextView.attributedText = textViewAttributedString
}
else if words!.contains(k) && y != nil {
let attributedString = NSMutableAttributedString(string: k)
attributedString.addAttribute(.font, value: UIFont(name: "Arial", size: 14.0)!, range: NSMakeRange(0, attributedString.length))
attributedString.addAttribute(.underlineStyle, value: 1, range: NSMakeRange(0, attributedString.length))
attributedString.addAttribute(.underlineColor, value: UIColor.link, range: NSMakeRange(0, attributedString.length))
attributedString.addAttribute(.foregroundColor, value: UIColor.link, range: NSMakeRange(0, attributedString.length))
attributedString.addAttribute(.link, value: k, range: NSMakeRange(0, attributedString.length))
formulaTextView.linkTextAttributes = [.foregroundColor: UIColor.link, .font: UIFont(name: "Arial", size: 14.0)!]
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .left
let range = y!.string.range(of: k)!
let nsrange = NSRange(range, in: y!.string)
y!.replaceCharacters(in: nsrange, with: attributedString)
y!.addAttribute(.paragraphStyle, value: paragraphStyle, range: NSMakeRange(0, y!.length))
formulaTextView.attributedText = y!
}
}
// Do any additional setup after loading the view.
}
formulaTextView.isEditable = false
formulaTextView.isSelectable = true
formulaTextView.isUserInteractionEnabled = true
formulaTextView.delegate = self
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
print("hello world")
return false
}

Customise embedded hyperlink in UITextView using Swift iOS13

Since installing iOS13 the UITextView extension is only customizing the background (to white color) around the text itself and not the entire UITextView.
How can I make sure that the entire UITextview object's background color is changed to white?
Extention:
extension UITextView {
func hyperLink(originalText: String, hyperLink: String, urlString: String) {
let style = NSMutableParagraphStyle()
style.alignment = .center
let attributedOriginalText = NSMutableAttributedString(string: originalText)
let linkRange = attributedOriginalText.mutableString.range(of: hyperLink)
let fullRange = NSMakeRange(0, attributedOriginalText.length)
attributedOriginalText.addAttribute(NSAttributedString.Key.link, value: urlString, range: linkRange)
attributedOriginalText.addAttribute(NSAttributedString.Key.paragraphStyle, value: style, range: fullRange)
attributedOriginalText.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.black, range: fullRange)
attributedOriginalText.addAttribute(NSAttributedString.Key.backgroundColor, value: UIColor.white, range: fullRange)
attributedOriginalText.addAttribute(NSAttributedString.Key.font, value: UIFont.systemFont(ofSize: 11), range: fullRange)
self.linkTextAttributes = [
kCTForegroundColorAttributeName: UIColor.black,
kCTUnderlineStyleAttributeName: NSUnderlineStyle.single.rawValue,
] as [NSAttributedString.Key : Any]
self.attributedText = attributedOriginalText
}//end func
}
Usage:
class LoginVC: UIViewController {
#IBOutlet weak var disclaimerTextView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
disclaimerTextView.hyperLink(originalText: "By continuing, you agree to our Terms and Privacy Policy found on our website", hyperLink: "website", urlString: WEBSITE_URL)
}
}
EDIT: output of the suggested solution - not working.
Changing the extension to this:
extension UITextView {
func hyperLink(originalText: String, hyperLink: String, urlString: String) {
let style = NSMutableParagraphStyle()
style.alignment = .center
let attributedOriginalText = NSMutableAttributedString(string: originalText)
let linkRange = attributedOriginalText.mutableString.range(of: hyperLink)
let fullRange = NSMakeRange(0, attributedOriginalText.length)
attributedOriginalText.addAttribute(NSAttributedString.Key.link, value: urlString, range: linkRange)
attributedOriginalText.addAttribute(NSAttributedString.Key.paragraphStyle, value: style, range: fullRange)
attributedOriginalText.addAttribute(NSAttributedString.Key.font, value: UIFont.systemFont(ofSize: 11), range: fullRange)
self.linkTextAttributes = [
kCTForegroundColorAttributeName: UIColor.black,
kCTUnderlineStyleAttributeName: NSUnderlineStyle.single.rawValue,
] as [NSAttributedString.Key : Any]
self.attributedText = attributedOriginalText
}
}
Is working for me. I simply removed the attributed text attributes that changed the foreground and background colors. I'm not sure why they were there to begin with.

NSRange with location on iOS13 Not Working

My code not working with NSRange location on iOS13, on iOS12 and below it's work. Is there a way to color the text from the letters to be colored until the total letters afterwards? because I only have data starting from the colored letters and the total letters afterwards.
override func viewDidLoad() {
super.viewDidLoad()
let text = "Testing Attributed Strings"
let attributedString = NSMutableAttributedString(string: text)
let dataStartIHave = 0
let dataTotalIHave = 7
attributedString.addAttribute(.foregroundColor, value: UIColor.red, range: NSRange(location: dataStartIHave, length: dataTotalIHave))
attributedLabel.attributedText = attributedString
}
Thanks in advance.
To get the range from the end of the word until the end of the text reliably you have to convert NSRange to Range<String.Index> and back
let text = "Testing Attributed Strings"
let attributedString = NSMutableAttributedString(string: text)
let dataStartIHave = 0
let dataTotalIHave = 7
let wordRange = NSRange(location: dataStartIHave, length: dataTotalIHave)
let upperBound = Range(wordRange, in: text)!.upperBound
let upperRange = NSRange(upperBound..., in: text)
attributedString.addAttribute(.foregroundColor, value: UIColor.red, range: upperRange)
attributedLabel.attributedText = attributedString
In Swift it's more efficient to get the Range<String.Index> from the word
let text = "Testing Attributed Strings"
let attributedString = NSMutableAttributedString(string: text)
if let testingRange = text.range(of: "Testing") {
let upperRange = NSRange(testingRange.upperBound..., in: text)
attributedString.addAttribute(.foregroundColor, value: UIColor.red, range: upperRange)
}
attributedLabel.attributedText = attributedString
This will work:
attributedString.addAttribute(.foregroundColor, value: UIColor.red, range: NSRange(location: dataStartIHave, length: dataTotalIHave))

swift - cell label.text is optional

I have every label in my tableViewCell displayed correctly, but only my attributeString output is "optional(1)"
let mString = String(self.productList?["market_price"].int)
let attributeString: NSMutableAttributedString = NSMutableAttributedString(string: mString)
attributeString.addAttribute(NSStrikethroughStyleAttributeName, value: 2, rnge: NSMakeRange(0, attributeString.length))
attributeString.addAttribute(NSStrikethroughColorAttributeName, value: UIColor.lightGrayColor(), range: NSMakeRange(0, attributeString.length))
self.marketPriceLabel.attributedText = attributeString
I found a solution.
let mInt: Int = (self.productList?["market_price"].int)!
let mString: String = String(mInt)
let attributeString: NSMutableAttributedString = NSMutableAttributedString(string: mString)
attributeString.addAttribute(NSStrikethroughStyleAttributeName, value: 2, rnge: NSMakeRange(0, attributeString.length))
attributeString.addAttribute(NSStrikethroughColorAttributeName, value: UIColor.lightGrayColor(), range: NSMakeRange(0, attributeString.length))
self.marketPriceLabel.attributedText = attributeString