Swift: HTML-Daten in einer Beschriftung oder Textansicht anzeigen

83

Ich habe einige HTML-Daten, die Überschriften, Absätze, Bilder und Listen-Tags enthalten.

Gibt es eine Möglichkeit, diese Daten in einem UITextViewoder UILabelmehreren anzuzeigen ?

Talha Ahmad Khan
quelle
1
Verwenden Sie UIWebView anstelle von UITextView oder UILabel. So wird es einschließlich Bilder angezeigt
Tyson Vignesh
Ja, ich denke du hast recht @TysonVignesh
Talha Ahmad Khan
@TysonVignesh Wie kann ich UIWebView verwenden, um HTML anzuzeigen?
Mohamed Ezzat
2
@ MohamedEzzat siehe diesen Link hackingwithswift.com/example-code/uikit/…
Talha Ahmad Khan

Antworten:

207

Für 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 ?? ""
    }
}

Wann immer Sie HTML-Text in eine UITextView einfügen möchten, verwenden Sie:

textView.attributedText = htmlText.htmlToAttributedString
Roger Carvalho
quelle
6
Das hat bei mir gut funktioniert, aber ich musste stattdessen label.attributedText verwenden.
Brent Waggoner
Toll! Ich musste nur die Codierungsdaten für osteuropäische lateinische Buchstaben in Unicode ändern.
Nja
Toll! aber label.attributedText sollte beim Aufruf von
label.text sein
6
soll das bilder bewahren?
daredevil1234
1
@ Roger Carvalho: Gibt es eine Möglichkeit, die Schriftfamilie, -größe usw. für die enthaltenen HTML-Tags festzulegen?
Bernhard Engl
35

Hier ist eine Swift 3-Version:

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
}

Ich habe hier Probleme mit einigen der anderen Antworten gefunden und es hat ein bisschen gedauert, bis ich das richtig verstanden habe. Ich habe den Zeilenumbruchmodus und die Anzahl der Zeilen so eingestellt, dass die Größe des Etiketts angemessen ist, wenn der HTML-Code mehrere Zeilen umfasst.

Garie
quelle
Der HTML-Code wurde analysiert ... aber falsch. Die Tags werden nicht mehr angezeigt, aber der fett gedruckte Text wird nicht angezeigt. Ich weiß nicht, welche Tags unterstützt werden, vielleicht auch <b>nicht.
Pablo
Fettgedruckte Tags funktionieren gut für mich. Können Sie Ihr vollständiges HTML posten, das nicht funktioniert? Möglicherweise wird die von Ihnen verwendete Schriftart nicht gut fett angezeigt.
Garie
Das HTML ist nur Text aus einem CMS-Editor, der so codiert ist, dass er in eine JSON-Zeichenfolge zurückkehrt. Die App greift auf den Webdienst zu und erhält den JSON, der dieses spezifische Textobjekt enthält. Die Anforderung des Clients besteht darin, dass dem Text HTML-Tags hinzugefügt werden können, ähnlich wie bei einem CMS (WordPress) einer Website. Vielleicht verschlüssele ich die Rücksendung falsch? Wenn ich den JSON analysiere, drucke ich die Zeichenfolgenrückgabe beim Debuggen und werde korrekt angezeigt, einschließlich des '<b> </ b>', aber sowohl auf dem Emulator als auch auf dem Gerät für Tests funktionieren die Tags nicht. Ich benutze Swift 3.
Pablo
3
Wie kann ich eine benutzerdefinierte Schriftart hinzufügen?
Bhavin Ramani
14

Fügen Sie diese Erweiterung hinzu, um Ihren HTML-Code in eine reguläre Zeichenfolge zu konvertieren:

    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 ?? ""
        }
}

Und dann zeigen Sie Ihren String in einem UITextView oder UILabel

textView.text = yourString.html2String oder

label.text = yourString.html2String
Himanshu
quelle
1
Ja, aber es funktioniert nur für Text im HTML. Ich war auch besorgt über die Bilder und die Listen. Gibt es eine Möglichkeit, die Bilder und Listen anzuzeigen, ist ein einzelnes Objekt?
Talha Ahmad Khan
@TalhaAhmadKhan Sie können eine UIWebView direkt verwenden, wenn Sie Bilder haben. TextView oder Beschriftungen funktionieren nicht, wie Sie wissen.
Sathe_Nagaraja
8

Danach hatte ich Probleme, Textattribute zu ändern, und ich konnte sehen, wie andere fragten, warum ...

Die beste Antwort ist also, stattdessen die Erweiterung mit NSMutableAttributedString zu verwenden:

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
    }
 }

}

Und dann können Sie es so verwenden:

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
            }
Kassy Barb
quelle
Ich möchte dasselbe erreichen, aber der obige Code funktioniert nicht.
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
Ved Rauniyar
quelle
6

Ich benutze dies:

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
        }
    }
}
Nikolay Khramchenko
quelle
1
Dies ist gut, gilt jedoch nur für UILabel. Es wäre viel besser, wenn es sich um eine generische Erweiterung handelt, die HTML verwendet und in zugeordneten Text konvertiert.
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 ?? ""
 }
}
Alex Morel
quelle
1
Swift 3.1 NSCharacterEncodingDocumentAttribute: String.Encoding.utf8.rawValue
Can 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
        }
    }
}

Und schließlich können Sie UILabel erstellen:

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
}

Ergebnis:

Geben Sie hier die Bildbeschreibung ein

Siehe Tutorial:

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

oscarr
quelle
2

Versuche dies:

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 ""
    }

Hoffe es ist hilfreich.

Iyyappan Ravi
quelle
Ja, aber es funktioniert nur für Text im HTML. Ich war auch besorgt über die Bilder und die Listen. Gibt es eine Möglichkeit, die Bilder und Listen anzuzeigen, ist ein einzelnes Objekt?
Talha Ahmad Khan
3
Es sollte beachtet werden , dass die Verwendung NSHTMLTextDocumentTypeist unglaublich langsam [1]. Versuchen Sie stattdessen, eine Bibliothek wie DDHTML zu verwenden. [1] robpeck.com/2015/04/nshtmltextdocumenttype-is-slow
Christopher Kevin Howell
2

Danke für die obige Antwort hier ist 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 ?? ""
    }
}
Stephen Chen
quelle
2

Für Swift 5 kann auch CSS geladen werden.

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
        }
    }
}

Wechseln Sie danach zu Ihrer Zeichenfolge, die Sie in NSAttributedString konvertieren möchten, und platzieren Sie sie wie im folgenden Beispiel:

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

Geben Sie hier die Bildbeschreibung ein Jeder Parameter benötigt Folgendes:

  • Schriftart: Fügen Sie Ihre Schriftart wie gewohnt in einem UILabel / UITextView hinzu, indem Sie UIFont mit dem Namen Ihrer benutzerdefinierten Schriftart und der Größe verwenden.
  • csscolor: Fügen Sie entweder Farbe im HEX-Format wie "# 000000" hinzu oder verwenden Sie den Namen der Farbe wie "Schwarz".
  • Zeilenhöhe: Dies ist der Abstand zwischen den Zeilen, wenn Sie mehrere Zeilen in einer UILabel / UITextView haben.
  • csstextalign: Es ist die Ausrichtung des Textes. Der Wert, den Sie hinzufügen müssen, ist "links" oder "rechts" oder "zentriert" oder "begründen".

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

Zgpeace
quelle
1

Wenn Sie HTML mit Bildern und einer Liste möchten, wird dies von UILabel nicht unterstützt. Ich habe jedoch festgestellt, dass YYText den Trick macht.

Christopher Kevin Howell
quelle
Es wird unterstützt, wenn Sie die Zeichenfolge richtig codieren. Es gibt eine attributedString-Erweiterung für HTML, die irgendwo
herumschwebt
1

Das Anzeigen von Bildern und Textabschnitten ist in a nicht möglich UITextViewoder UILabelSie müssen dazu a verwenden UIWebView.

Fügen Sie einfach das Element in das Storyboard ein, verknüpfen Sie es mit Ihrem Code und rufen Sie es auf, um die URL zu laden.

OBJ-C

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

Schnell

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

Schritt für Schritt Tutorial. http://sourcefreeze.com/uiwebview-example-using-swift-in-ios/

Ulysses
quelle
Es ist in beiden möglich. Die Zeichenfolge muss nur richtig codiert werden
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
    }
}

Anruf:

myLabel.attributedText = "myString".htmlAttributedString()
Álvaro Agüero
quelle
-1

Wenn Sie einen String mit HTML-Code im Inneren haben, können Sie Folgendes verwenden:

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 
    }
}

UND IN IHREM CODE VERWENDEN SIE:

label.text = "something".htmlString
Pedro Menezes
quelle