Display attributed text in textview in swift 3? - html

I want to display text in Italic ,bold which is received from server .
< p > < b > < i > hello < /i > < /b > < i >world< /i >< /p > so,
responseObj!["text"] = "<p><b><i>hello</i></b><i>world</></p>"
if let postText:String = responseObj!["text"] as? String{
let str = try NSAttributedString(data: postText.data(using: String.Encoding.unicode, allowLossyConversion: true)!, options: [ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil)
self.textView.attributedText = str
}
when i am adding like this means my text displays normal without applying bold & italic . I want text to be displayed in bold ,italic .

EDIT: Updated Swift 4
Create an extension for String:
extension String {
func htmlAttributedString(fontSize: CGFloat = 17.0) -> NSAttributedString? {
let fontName = UIFont.systemFont(ofSize: fontSize).fontName
let string = self.appending(String(format: "<style>body{font-family: '%#'; font-size:%fpx;}</style>", fontName, fontSize))
guard let data = string.data(using: String.Encoding.utf16, allowLossyConversion: false) else { return nil }
guard let html = try? NSMutableAttributedString (
data: data,
options: [NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html],
documentAttributes: nil) else { return nil }
return html
}
}
Invoke it anywhere in your project:
text.htmlAttributedString() // will set fontSize with 17.0 which is the default value
text.htmlAttributedString(fontSize: 14.0) // pass your required fontSize
Note, that let string = self.appending(String(format: "<style>body{font-family: '%#'; font-size:%fpx;}</style>", fontName, fontSize)) is used to keep the string font as same as the font used in default iOS platform.
To set the string on UITextView use:
textView.attributedText = textToBeConverted.htmlAttributedString() ?? ""
RESULT:

Assign Attributed text to UITextView from below function,
//HTML to Attributed text
func stringFromHtml(string: String) -> NSAttributedString? {
do {
let data = string.data(using: String.Encoding.utf8, allowLossyConversion: true)
if let d = data {
let str = try NSAttributedString(data: d,
options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
documentAttributes: nil)
return str
}
} catch {
}
return nil
}
//This will give you attributed text which you have to assign to your UITextView. and whatever string having html tag that you have to pass inside this function.
//Below code will conver attributed text to HTML Text
//Attributed to HTML text
let attrStr = self.txtView.attributedText
let documentAttributes = [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType]
do {
let htmlData = try attrStr?.data(from: NSMakeRange(0, (attrStr?.length)!), documentAttributes:documentAttributes)
if let htmlString = String(data:htmlData!, encoding:String.Encoding.utf8) {
print(htmlString)
}
}
catch {
print("error creating HTML from Attributed String")
}

Related

How to display links and images from an HTML String

I have a string that contains HTML code. What is the best way to display that (it contains images), also I want to make links in that tappable (open in Safari)
I have tried String extension that gives me NSAttributedString from HTML, but the image is only partially shown and links are not tappable.
let text = htmlString.attributedString(withRegularFont: UIFont.systemFont(ofSize: 14), andBoldFont: UIFont.systemFont(ofSize: 16))
extension String {
func attributedString(withRegularFont regularFont: UIFont, andBoldFont boldFont: UIFont, textColor: UIColor = UIColor.gray) -> NSMutableAttributedString {
var attributedString = NSMutableAttributedString()
guard let data = self.data(using: .utf8) else { return NSMutableAttributedString() }
do {
attributedString = try NSMutableAttributedString(data: data,
options: [.documentType: NSAttributedString.DocumentType.html,
.characterEncoding:String.Encoding.utf8.rawValue],
documentAttributes: nil)
let range = NSRange(location: 0, length: attributedString.length)
attributedString.enumerateAttribute(NSAttributedString.Key.font, in: range, options: .longestEffectiveRangeNotRequired) { value, range, _ in
let currentFont: UIFont = value as! UIFont
var replacementFont: UIFont? = nil
if currentFont.fontName.contains("bold") || currentFont.fontName.contains("Semibold") {
replacementFont = boldFont
} else {
replacementFont = regularFont
}
let replacementAttribute = [NSAttributedString.Key.font:replacementFont!, NSAttributedString.Key.foregroundColor: textColor]
attributedString.addAttributes(replacementAttribute, range: range)
} catch let e {
print(e.localizedDescription)
}
return attributedString
}
}
It shows me the HTML inside the UILabel but I am not able to tap on links and images are cropped respective to device width.
I think that the best option is to save this html string as a file and then load this file using web view.
check this question

iOS 11 changes font family while converting HTML to NSAttributedString

I have a string extension that converts HTML to an NSAttributedString, but i add my own custom font to the HTML string from an API before formatting in the following way.
let testString = "<span style="font-family: MuseoSans-900"> This is an html String <i> with italics </i> and a custom font </span>"
guard let htmlData = testString.data(using: .utf8) else { return nil }
do {
let attrString = try NSAttributedString(data: htmlData, options: [
NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
NSCharacterEncodingDocumentAttribute: String.Encoding.utf8.rawValue,
], documentAttributes: nil)
let formattedHTMLString = NSMutableAttributedString(attributedString: HTMLString)
formattedHTMLString.beginEditing()
formattedHTMLString.enumerateAttribute(NSFontAttributeName, in: NSMakeRange(0, formattedHTMLString.length), options: []){
(_ value: Any?, _ range: NSRange, _ stop: UnsafeMutablePointer) -> Void in
if value != nil {
var oldFont = value as? UIFont
print("\(oldFont?.fontName)")
}
}
return formattedHTMLString
} catch let error as NSError {
print(error.localizedDescription)
return nil
}
On iOS 10 < the attributed string is returned with the entire string having the same font (in this case MuseoSans-900) including the italized part of the html string but on iOS 11 it updates and changes the font to MuseoSans-300 for the italics part of the html string and keeps the rest of the string MuseoSans-900 during the conversion to NSAttributed string..I do not know why this is happening and any help would be greatly appreciated.

NSAttributedString to HTML in iOS Swift 3

I have searched a lot but can only find HTML to plain text, not the other way around, I have email implementation in my app, thus need to send the content of email as HTML to the backend.
Edit 1: I have rich text that includes bold, italic, ordered/unordered list, underlined words.
If you are looking to convert NSAttributedString to String, here is the extension method you are looking for. Simply call yourAttributtedString.htmlString() and print it out.
extension NSAttributedString {
func htmlString() -> String? {
let documentAttributes = [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType]
do {
let htmlData = try self.data(from: NSMakeRange(0, self.length), documentAttributes:documentAttributes)
if let htmlString = String(data:htmlData, encoding:String.Encoding.utf8) {
return htmlString
}
}
catch {}
return nil
}
}
According to this post:
private func getHtmlLabel(text: String) -> UILabel {
let label = UILabel()
label.numberOfLines = 0
label.lineBreakMode = .byWordWrapping
label.attributedString = stringFromHtml(string: text)
return label
}
private func stringFromHtml(string: String) -> NSAttributedString? {
do {
let data = string.data(using: String.Encoding.utf8, allowLossyConversion: true)
if let d = data {
let str = try NSAttributedString(data: d,
options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
documentAttributes: nil)
return str
}
} catch { }
return nil
}

How to remove whitespace between two paragraphs?

My image
I am getting data from Html to the text.
Now please tell me how to avoid the space between two paragraphs ?
func processGetDescriptionResponse(json: JSON) {
let status = json.dictionaryObject!["status"] as? Bool
if status == true {
let data = json.dictionaryValue["data"]!
let values = data.arrayValue
dataSourceDescription.removeAll()
for i in 0 ..< values.count {
let description = Description.initWithJSON(values[i])
dataSourceDescription.append(description)
// DetailDescription.text = dataSourceDescription[i].content
if dataSourceDescription[i].file_url == ""
{
DetailImage.image = UIImage(named: "logo_two_fifty")
}
else
{
let imageURL = NSURL(string: baseURLString + dataSourceDescription[i].file_url!)
DetailImage.kf_setImageWithURL(imageURL!, placeholderImage: nil, optionsInfo: [.Transition(ImageTransition.Fade(50))]) { (image, error, cacheType, imageURL) in
}
}
DetailDescription.attributedText = convertText(dataSourceDescription[i].content!)
print(DetailDescription.text)
}
} else {
}
}
If you receive html content, you can display it in UITextView using NSAttributedString:
let htmlString = "<html><body><p>Para 1</p><p>Para 2</p></body></html>"
let attributedString = try!
NSAttributedString(data: htmlString.dataUsingEncoding(NSUnicodeStringEncoding, allowLossyConversion: false)!,
options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
documentAttributes: nil)
yourTextView.attributedText = attributedString

HTML string to formatted text in Swift

Hello I have a string that I want to write to a text document in Swift. Because the text document has line breaks, however, the string seems to be in HTML format.
Here is what I want to do:
//Covert str1 to str2
var str1 = "1<div>2</div><div>3</div><div>4</div>"
var str2 = "1
2
3
4" //Text document will have text that looks like this (With line breaks)
You can try with NSAttributedString:
let htmlString = "1<div>2</div><div>3</div><div>4</div>"
NSAttributedString(data: htmlString.dataUsingEncoding(NSUnicodeStringEncoding)!,
options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
documentAttributes: nil,
error: nil);
this will produce:
"1\n2\n3\n4\n"
Swift 3.0: You can pop this directly into Xcode's playground to check it out.
let htmlString = "1<div>2</div><div>3</div><div>4</div>"
func getHtmlFormat(fromString htmlString: String) -> NSAttributedString? {
guard let htmlData = htmlString.data(using: String.Encoding.unicode) else
{
print("Could not get htmlData")
return nil
}
do {
return try NSAttributedString(data: htmlData, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil)
} catch let error {
print(error)
return nil
}
}
let textView = UITextView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
textView.attributedText = getHtmlFormat(fromString: htmlString)