Swift: Hiển thị dữ liệu HTML trong nhãn hoặc textView


83

Tôi có một số dữ liệu HTML, chứa các thẻ tiêu đề, đoạn văn, hình ảnh và danh sách.

Có cách nào để hiển thị dữ liệu này trong một UITextViewhoặc UILabelkhông?


1
Sử dụng UIWebView thay vì UITextView hoặc UILabel. Vì vậy, nó sẽ hiển thị bao gồm cả hình ảnh
Tyson Vignesh

Đúng, tôi nghĩ bạn đúng @TysonVignesh
Talha Ahmad Khan,

@TysonVignesh Làm cách nào để sử dụng UIWebView để hiển thị html?
Mohamed Ezzat

2
@MohamedEzzat xem liên kết này hackingwithswift.com/example-code/uikit/…
Talha Ahmad Khan

Câu trả lời:


206

Đối với Swift 5:

extension String {
    var htmlToAttributedString: NSAttributedString? {
        guard let data = data(using: .utf8) else { return nil }
        do {
            return try NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding:String.Encoding.utf8.rawValue], documentAttributes: nil)
        } catch {
            return nil
        }
    }
    var htmlToString: String {
        return htmlToAttributedString?.string ?? ""
    }
}

Sau đó, bất cứ khi nào bạn muốn đặt văn bản HTML trong UITextView, hãy sử dụng:

textView.attributedText = htmlText.htmlToAttributedString

6
Điều này rất hiệu quả đối với tôi, nhưng thay vào đó tôi phải sử dụng label.attributedText.
Brent Wagoner

Tuyệt quá! Tôi chỉ cần thay đổi dữ liệu mã hóa thành unicode, đối với các chữ cái Latinh Đông Âu.
nja

Tuyệt quá! nhưng label.attributedText nên label.text khi gọi
Sazzad Hissain Khan

6
điều này có phải là để bảo tồn hình ảnh?
dámevil1234

1
@Roger Carvalho: Có cách nào để đặt font-family, -size, v.v. cho các thẻ html có trong đó không?
Bernhard Engl

35

Đây là phiên bản Swift 3:

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
}

Tôi đã tìm thấy các vấn đề với một số câu trả lời khác ở đây và tôi phải mất một chút để giải quyết vấn đề này đúng. Tôi đặt chế độ ngắt dòng và số dòng để nhãn có kích thước thích hợp khi HTML kéo dài nhiều dòng.


HTML đã được phân tích cú pháp ... nhưng không chính xác. Các thẻ không còn xuất hiện, nhưng văn bản in đậm không được hiển thị. Tôi không biết thẻ nào được hỗ trợ, có thể <b>là không.
Pablo

Thẻ in đậm hoạt động tốt đối với tôi. Bạn có thể đăng html đầy đủ của mình không hoạt động không? Có thể phông chữ bạn đang sử dụng không hiển thị đậm tốt.
garie

Html chỉ là văn bản từ trình soạn thảo CMS, được mã hóa để trả về một chuỗi JSON. Ứng dụng truy cập dịch vụ web, lấy JSON chứa đối tượng văn bản cụ thể này - yêu cầu từ khách hàng ở đây là khả năng thêm thẻ html vào văn bản, tương tự như CMS (wordpress) của một trang web. Có lẽ tôi đang mã hóa trả lại không chính xác? Khi tôi phân tích cú pháp JSON, tôi in chuỗi trả về khi gỡ lỗi và xuất hiện chính xác, bao gồm cả '<b> </b>', nhưng trên cả trình mô phỏng và thiết bị để kiểm tra, các thẻ sẽ không hoạt động. Tôi đang sử dụng Swift 3.
Pablo

3
Làm cách nào để thêm phông chữ tùy chỉnh?
Bhavin Ramani

14

Thêm phần mở rộng này để chuyển đổi mã html của bạn thành một chuỗi thông thường:

    extension String {

        var html2AttributedString: NSAttributedString? {
            guard
                let data = dataUsingEncoding(NSUTF8StringEncoding)
            else { return nil }
            do {
                return try NSAttributedString(data: data, options: [NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType,NSCharacterEncodingDocumentAttribute:NSUTF8StringEncoding], documentAttributes: nil)
            } catch let error as NSError {
                print(error.localizedDescription)
                return  nil
            }
        }
        var html2String: String {
            return html2AttributedString?.string ?? ""
        }
}

Và sau đó, bạn hiển thị Chuỗi của mình bên trong UITextView Hoặc UILabel

textView.text = yourString.html2String hoặc là

label.text = yourString.html2String

1
Có nhưng nó chỉ hoạt động đối với văn bản trong HTML. Tôi cũng lo lắng về hình ảnh và danh sách. Có cách nào để hiển thị hình ảnh và danh sách là đối tượng duy nhất không ??
Talha Ahmad Khan

@TalhaAhmadKhan bạn có thể trực tiếp sử dụng UIWebView nếu bạn có Hình ảnh. TextView hoặc các nhãn sẽ không hoạt động như bạn biết.
Sathe_Nagaraja

8

Tôi đã gặp sự cố khi thay đổi các thuộc tính của văn bản sau đó và tôi có thể thấy những người khác hỏi tại sao ...

Vì vậy, câu trả lời tốt nhất là sử dụng tiện ích mở rộng với NSMutableAttributedString để thay thế:

extension String {

 var htmlToAttributedString: NSMutableAttributedString? {
    guard let data = data(using: .utf8) else { return nil }
    do {
        return try NSMutableAttributedString(data: data,
                                      options: [.documentType: NSMutableAttributedString.DocumentType.html,
                                                .characterEncoding: String.Encoding.utf8.rawValue],
                                      documentAttributes: nil)
    } catch let error as NSError {
        print(error.localizedDescription)
        return  nil
    }
 }

}

Và sau đó bạn có thể sử dụng nó theo cách này:

if let labelTextFormatted = text.htmlToAttributedString {
                let textAttributes = [
                    NSAttributedStringKey.foregroundColor: UIColor.white,
                    NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: 13)
                    ] as [NSAttributedStringKey: Any]
                labelTextFormatted.addAttributes(textAttributes, range: NSRange(location: 0, length: labelTextFormatted.length))
                self.contentText.attributedText = labelTextFormatted
            }

Tôi muốn đạt được điều tương tự nhưng mã trên không hoạt động.
Pratyush Pratik

7

Swift 3.0

var attrStr = try! NSAttributedString(
        data: "<b><i>text</i></b>".data(using: String.Encoding.unicode, allowLossyConversion: true)!,
        options: [ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
        documentAttributes: nil)
label.attributedText = attrStr

6

Tôi đang sử dụng cái này:

extension UILabel {
    func setHTML(html: String) {
        do {
            let attributedString: NSAttributedString = try NSAttributedString(data: html.data(using: .utf8)!, options: [NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType], documentAttributes: nil)
            self.attributedText = attributedString
        } catch {
            self.text = html
        }
    }
}

1
Điều này là tốt nhưng sẽ chỉ áp dụng cho UILabel. Sẽ tốt hơn nhiều nếu đó là phần mở rộng chung sẽ lấy html và chuyển đổi thành văn bản được quy.
i.AsifNoor

4

Swift 3

extension String {


var html2AttributedString: NSAttributedString? {
    guard
        let data = data(using: String.Encoding.utf8)
        else { return nil }
    do {
        return try NSAttributedString(data: data, options: [NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType,NSCharacterEncodingDocumentAttribute:String.Encoding.utf8], documentAttributes: nil)
    } catch let error as NSError {
        print(error.localizedDescription)
        return  nil
    }
}
var html2String: String {
    return html2AttributedString?.string ?? ""
 }
}

1
swift 3.1 NSCharacterEncodingDocumentAttribute: String.Encoding.utf8.rawValue
Có thể Aksoy

3

Swift 5

extension UIColor {
    var hexString: String {
        let components = cgColor.components
        let r: CGFloat = components?[0] ?? 0.0
        let g: CGFloat = components?[1] ?? 0.0
        let b: CGFloat = components?[2] ?? 0.0

        let hexString = String(format: "#%02lX%02lX%02lX", lroundf(Float(r * 255)), lroundf(Float(g * 255)),
                               lroundf(Float(b * 255)))

        return hexString
    }
}
extension String {
    func htmlAttributed(family: String?, size: CGFloat, color: UIColor) -> NSAttributedString? {
        do {
            let htmlCSSString = "<style>" +
                "html *" +
                "{" +
                "font-size: \(size)pt !important;" +
                "color: #\(color.hexString) !important;" +
                "font-family: \(family ?? "Helvetica"), Helvetica !important;" +
            "}</style> \(self)"

            guard let data = htmlCSSString.data(using: String.Encoding.utf8) else {
                return nil
            }

            return try NSAttributedString(data: data,
                                          options: [.documentType: NSAttributedString.DocumentType.html,
                                                    .characterEncoding: String.Encoding.utf8.rawValue],
                                          documentAttributes: nil)
        } catch {
            print("error: ", error)
            return nil
        }
    }
}

Và cuối cùng, bạn có thể tạo UILabel:

func createHtmlLabel(with html: String) -> UILabel {
    let htmlMock = """
    <b>hello</b>, <i>world</i>
    """

    let descriprionLabel = UILabel()
    descriprionLabel.attributedText = htmlMock.htmlAttributed(family: "YourFontFamily", size: 15, color: .red)

    return descriprionLabel
}

Kết quả:

nhập mô tả hình ảnh ở đây

Xem hướng dẫn:

https://medium.com/@valv0/a-swift-extension-for-string-and-html-8cfb7477a510


2

Thử đi:

let label : UILable! = String.stringFromHTML("html String")

func stringFromHTML( string: String?) -> String
    {
        do{
            let str = try NSAttributedString(data:string!.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true
                )!, options:[NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: NSNumber(unsignedLong: NSUTF8StringEncoding)], documentAttributes: nil)
            return str.string
        } catch
        {
            print("html error\n",error)
        }
        return ""
    }

Hy vọng nó hữu ích.


Có nhưng nó chỉ hoạt động đối với văn bản trong HTML. Tôi cũng lo lắng về hình ảnh và danh sách. Có cách nào để hiển thị hình ảnh và danh sách là đối tượng duy nhất không ??
Talha Ahmad Khan

3
Cần lưu ý rằng việc sử dụng NSHTMLTextDocumentTypevô cùng chậm [1]. Hãy thử và sử dụng một thư viện như DDHTML để thay thế. [1] robpeck.com/2015/04/nshtmltextdocumenttype-is-slow
Christopher Kevin Howell

2

Thx cho câu trả lời ở trên ở đây là Swift 4.2


extension String {

    var htmlToAttributedString: NSAttributedString? {
        guard
            let data = self.data(using: .utf8)
            else { return nil }
        do {
            return try NSAttributedString(data: data, options: [
                NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html,
                NSAttributedString.DocumentReadingOptionKey.characterEncoding: String.Encoding.utf8.rawValue
                ], documentAttributes: nil)
        } catch let error as NSError {
            print(error.localizedDescription)
            return  nil
        }
    }

    var htmlToString: String {
        return htmlToAttributedString?.string ?? ""
    }
}

2

Đối với Swift 5, nó cũng có thể tải css.

extension String {
    public var convertHtmlToNSAttributedString: NSAttributedString? {
        guard let data = data(using: .utf8) else {
            return nil
        }
        do {
            return try NSAttributedString(data: data,options: [.documentType: NSAttributedString.DocumentType.html,.characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil)
        }
        catch {
            print(error.localizedDescription)
            return nil
        }
    }

    public func convertHtmlToAttributedStringWithCSS(font: UIFont? , csscolor: String , lineheight: Int, csstextalign: String) -> NSAttributedString? {
        guard let font = font else {
            return convertHtmlToNSAttributedString
        }
        let modifiedString = "<style>body{font-family: '\(font.fontName)'; font-size:\(font.pointSize)px; color: \(csscolor); line-height: \(lineheight)px; text-align: \(csstextalign); }</style>\(self)";
        guard let data = modifiedString.data(using: .utf8) else {
            return nil
        }
        do {
            return try NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil)
        }
        catch {
            print(error)
            return nil
        }
    }
}

Sau đó, chuyển đến chuỗi của bạn mà bạn muốn chuyển đổi thành NSAttributedString và đặt nó như ví dụ bên dưới:

myUILabel.attributedText = "Swift is awesome&#33;&#33;&#33;".convertHtmlToAttributedStringWithCSS(font: UIFont(name: "Arial", size: 16), csscolor: "black", lineheight: 5, csstextalign: "center")

nhập mô tả hình ảnh ở đây Đây là những gì mọi tham số nhận:

  • phông chữ: Thêm phông chữ của bạn như thường làm trong UILabel / UITextView, sử dụng UIFont với tên phông chữ tùy chỉnh của bạn và kích thước.
  • csscolor: Thêm màu ở định dạng HEX, như "# 000000" hoặc sử dụng tên của màu, như "đen".
  • lineheight: Đó là khoảng cách giữa các dòng khi bạn có nhiều dòng trong UILabel / UITextView.
  • csstextalign: Đó là căn chỉnh của văn bản, giá trị bạn cần thêm là "left" hoặc "right" hoặc "center" hoặc "justify"

Tham khảo: https://johncodeos.com/how-to-display-html-in-uitextview-uilabel-with-custom-color-font-etc-in-ios-using-swift/


1

Nếu bạn muốn HTML, với hình ảnh và danh sách, điều này không được UILabel hỗ trợ. Tuy nhiên, tôi đã tìm thấy YYText thực hiện thủ thuật.


Nó được hỗ trợ nếu bạn mã hóa chuỗi đúng cách. Có một phần mở rộng thuộc về chuỗi phân bổ cho HTML trôi nổi ở đâu đó
froggomad

1

Không thể hiển thị hình ảnh và đoạn văn bản trong a UITextViewhoặc UILabel, để làm điều này, bạn phải sử dụng a UIWebView.

Chỉ cần thêm mục vào bảng phân cảnh, liên kết với mã của bạn và gọi nó để tải URL.

OBJ-C

NSString *fullURL = @"http://conecode.com";
NSURL *url = [NSURL URLWithString:fullURL];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[_viewWeb loadRequest:requestObj];

Nhanh

let url = NSURL (string: "http://www.sourcefreeze.com");
let requestObj = NSURLRequest(URL: url!);
viewWeb.loadRequest(requestObj);

Hướng dẫn từng bước. http://sourcefreeze.com/uiwebview-example-using-swift-in-ios/


Nó có thể ở cả hai. Chuỗi chỉ cần được mã hóa đúng cách
froggomad

1

Swift 5

extension String {
    func htmlAttributedString() -> NSAttributedString? {
        guard let data = self.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
    }
}

Gọi:

myLabel.attributedText = "myString".htmlAttributedString()

-1

NẾU BẠN CÓ STRING CÓ MÃ HTML BÊN TRONG, BẠN CÓ THỂ SỬ DỤNG:

extension String {
var utfData: Data? {
        return self.data(using: .utf8)
    }

    var htmlAttributedString: NSAttributedString? {
        guard let data = self.utfData else {
            return nil
        }
        do {
            return try NSAttributedString(data: data,
                                          options: [
                                            .documentType: NSAttributedString.DocumentType.html,
                                            .characterEncoding: String.Encoding.utf8.rawValue
                ], documentAttributes: nil)
        } catch {
            print(error.localizedDescription)
            return nil
        }
    }

    var htmlString: String {
        return htmlAttributedString?.string ?? self 
    }
}

VÀ TRONG MÃ CỦA BẠN BẠN SỬ DỤNG:

label.text = "something".htmlString
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.