Question

Je me sers d'une instance de UIWebView pour traiter un texte et la couleur correctement, il donne le résultat au format HTML, mais plutôt que de l'afficher dans la UIWebView je veux afficher à l'aide Core Text avec un NSAttributedString.

Je suis en mesure de créer et d'en tirer le NSAttributedString mais je ne suis pas sûr que je peux convertir et cartographier le HTML dans la chaîne attribuée.

Je comprends que sous Mac OS X NSAttributedString a une méthode initWithHTML:, mais ce fut un Mac ne plus et ne sont pas disponibles pour iOS.

Je sais aussi qu'il ya une question similaire à cela, mais il y avait pas de réponse, je pensais que je voudrais essayer à nouveau et voir si quelqu'un a créé une façon de le faire et si oui, si elles pouvaient partager.

Était-ce utile?

La solution

iOS 7, UIKit a ajouté un initWithData:options:documentAttributes:error: méthode qui peut initialiser un NSAtttributedString en utilisant HTML, par exemple:

[[NSAttributedString alloc] initWithData:[htmlString dataUsingEncoding:NSUTF8StringEncoding] 
                                 options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
                                           NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)} 
                      documentAttributes:nil error:nil];

Swift:

let htmlData = NSString(string: details).data(using: String.Encoding.unicode.rawValue)
let options = [NSAttributedString.DocumentReadingOptionKey.documentType:
        NSAttributedString.DocumentType.html]
let attributedString = try? NSMutableAttributedString(data: htmlData ?? Data(),
                                                          options: options,
                                                          documentAttributes: nil)

Autres conseils

Il y a un travail en cours plus open source à NSAttributedString par Oliver Drobnik à Github. Il utilise NSScanner pour l'analyse syntaxique HTML.

Création doit être fait un NSAttributedString de HTML sur le thread principal!

Mise à jour: Il se trouve que NSAttributedString HTML rendu dépend de WebKit sous le capot, et doit être exécuté sur le thread principal ou il parfois planter l'application avec un SIGTRAP .

New Relic journal plantage:

 entrer image description ici

Voici une mise à jour thread-safe Swift 2 Extension chaîne:

extension String {
    func attributedStringFromHTML(completionBlock:NSAttributedString? ->()) {
        guard let data = dataUsingEncoding(NSUTF8StringEncoding) else {
            print("Unable to decode data from html string: \(self)")
            return completionBlock(nil)
        }

        let options = [NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType,
                   NSCharacterEncodingDocumentAttribute: NSNumber(unsignedInteger:NSUTF8StringEncoding)]

        dispatch_async(dispatch_get_main_queue()) {
            if let attributedString = try? NSAttributedString(data: data, options: options, documentAttributes: nil) {
                completionBlock(attributedString)
            } else {
                print("Unable to create attributed string from html string: \(self)")
                completionBlock(nil)
            }
        }
    }
}

Utilisation:

let html = "<center>Here is some <b>HTML</b></center>"
html.attributedStringFromHTML { attString in
    self.bodyLabel.attributedText = attString
}

Sortie:

 entrer image description ici

Swift initialiseur l'extension sur NSAttributedString

Mon inclination était d'ajouter cela comme une extension NSAttributedString plutôt que String. Je l'ai essayé comme une extension statique et un initialiseur. Je préfère le initialiseur qui est ce que j'ai inclus ci-dessous.

Swift 4

internal convenience init?(html: String) {
    guard let data = html.data(using: String.Encoding.utf16, allowLossyConversion: false) else {
        return nil
    }

    guard let attributedString = try?  NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil) else {
        return nil
    }

    self.init(attributedString: attributedString)
}

Swift 3

extension NSAttributedString {

internal convenience init?(html: String) {
    guard let data = html.data(using: String.Encoding.utf16, allowLossyConversion: false) else {
        return nil
    }

    guard let attributedString = try? NSMutableAttributedString(data: data, options: [NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html], documentAttributes: nil) else {
        return nil
    }

    self.init(attributedString: attributedString)
}
}

Exemple

let html = "<b>Hello World!</b>"
let attributedString = NSAttributedString(html: html)

Ceci est une extension de String écrit à Swift pour retourner une chaîne HTML comme NSAttributedString.

extension String {
    func htmlAttributedString() -> NSAttributedString? {
        guard let data = self.dataUsingEncoding(NSUTF16StringEncoding, allowLossyConversion: false) else { return nil }
        guard let html = try? NSMutableAttributedString(data: data, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil) else { return nil }
        return html
    }
}

Pour utiliser,

label.attributedText = "<b>Hello</b> \u{2022} babe".htmlAttributedString()

Dans ce qui précède, j'ai volontairement ajouté une unicode \ u2022 pour montrer qu'elle rend unicode correctement.

trivial. Le codage par défaut que les utilisations de NSAttributedString est NSUTF16StringEncoding (non UTF8)

Swift 3.0 Xcode 8 Version

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: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil) else { return nil }
    return html
}

Swift 4


  • NSAttributedString commodité initialiseur
  • Sans gardes supplémentaires
  • jette erreur

extension NSAttributedString {

    convenience init(htmlString html: String) throws {
        try self.init(data: Data(html.utf8), options: [
            .documentType: NSAttributedString.DocumentType.html,
            .characterEncoding: String.Encoding.utf8.rawValue
        ], documentAttributes: nil)
    }

}

Utilisation

UILabel.attributedText = try? NSAttributedString(htmlString: "<strong>Hello</strong> World!")

La seule solution que vous avez droit est maintenant d'analyser le code HTML, construire des noeuds avec le point / font / etc données attributs, puis les combiner dans un NSAttributedString. Il est beaucoup de travail, mais si elle est faite correctement, peut être réutilisable dans l'avenir.

a fait quelques modifications sur solution de Andrew et mettre à jour le code Swift 3:

Ce code utilise maintenant UITextView comme self et capable d'hériter de sa police d'origine, taille de la police et la couleur du texte

Remarque: toHexString() est l'extension de

extension UITextView {
    func setAttributedStringFromHTML(_ htmlCode: String, completionBlock: @escaping (NSAttributedString?) ->()) {
        let inputText = "\(htmlCode)<style>body { font-family: '\((self.font?.fontName)!)'; font-size:\((self.font?.pointSize)!)px; color: \((self.textColor)!.toHexString()); }</style>"

        guard let data = inputText.data(using: String.Encoding.utf16) else {
            print("Unable to decode data from html string: \(self)")
            return completionBlock(nil)
        }

        DispatchQueue.main.async {
            if let attributedString = try? NSAttributedString(data: data, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil) {
                self.attributedText = attributedString
                completionBlock(attributedString)
            } else {
                print("Unable to create attributed string from html string: \(self)")
                completionBlock(nil)
            }
        }
    }
}

Exemple d'utilisation:

mainTextView.setAttributedStringFromHTML("<i>Hello world!</i>") { _ in }

La solution ci-dessus est correcte.

[[NSAttributedString alloc] initWithData:[htmlString dataUsingEncoding:NSUTF8StringEncoding] 
                                 options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
                                           NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)} 
                      documentAttributes:nil error:nil];

Mais l'application wioll plantage si vous exécutez sur ios 8.1,2 ou 3.

Pour éviter l'accident ce que vous pouvez faire est: exécuter ce dans une file d'attente. Pour que ce soit toujours le fil conducteur.

L'utilisation de NSHTMLTextDocumentType est lent et il est difficile de styles de contrôle. Je vous suggère d'essayer ma bibliothèque qui est appelée Atributika. Il a son propre analyseur HTML très rapide. vous pouvez aussi avoir des noms de balises et de définir tous les styles pour eux.

Exemple:

let str = "<strong>Hello</strong> World!".style(tags:
    Style("strong").font(.boldSystemFont(ofSize: 15))).attributedString

label.attributedText = str

Vous pouvez trouver ici https://github.com/psharanda/Atributika

Swift 3 :
Essayer cette :

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: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
            documentAttributes: nil) else { return nil }
        return html
    }
}  

Et pour l'utilisation:

let str = "<h1>Hello bro</h1><h2>Come On</h2><h3>Go sis</h3><ul><li>ME 1</li><li>ME 2</li></ul> <p>It is me bro , remember please</p>"

self.contentLabel.attributedText = str.htmlAttributedString()

Extensions utiles

Inspiré par ce fil, une nacelle, et l'exemple ObjC Erica Sadun dans iOS Gourmet livre de recettes p.80, je l'ai écrit une extension sur String et NSAttributedString aller-retour entre HTML simples cordes et NSAttributedStrings et vice versa - sur GitHub que j'ai trouvé utile.

signatures sont (encore une fois, le code complet dans un Gist, lien ci-dessus):

extension NSAttributedString {
    func encodedString(ext: DocEXT) -> String?
    static func fromEncodedString(_ eString: String, ext: DocEXT) -> NSAttributedString? 
    static func fromHTML(_ html: String) -> NSAttributedString? // same as above, where ext = .html
}

extension String {
    func attributedString(ext: DocEXT) -> NSAttributedString?
}

enum DocEXT: String { case rtfd, rtf, htm, html, txt }

avec la police

extension NSAttributedString
{
internal convenience init?(html: String, font: UIFont? = nil) {
    guard let data = html.data(using: String.Encoding.utf16, allowLossyConversion: false) else {
        return nil
    }
    assert(Thread.isMainThread)
    guard let attributedString = try?  NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil) else {
        return nil
    }
    let mutable = NSMutableAttributedString(attributedString: attributedString)
    if let font = font {
        mutable.addAttribute(.font, value: font, range: NSRange(location: 0, length: mutable.length))
    }
    self.init(attributedString: mutable)
}
}

vous pouvez également utiliser les versions cela a été dérivée de et ensemble police sur UILabel après avoir réglé attributedString

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top