158 votes

Convertir HTML en NSAttributedString dans iOS

J'utilise une instance de UIWebView pour traiter du texte et le colorer correctement, il donne le résultat en HTML, mais au lieu de l'afficher dans la fenêtre UIWebView Je veux l'afficher en utilisant Core Text avec un NSAttributedString .

Je suis capable de créer et de dessiner le NSAttributedString mais je ne sais pas comment convertir et mapper le HTML dans la chaîne attribuée.

Je comprends que sous Mac OS X NSAttributedString a une initWithHTML: mais il s'agit d'un ajout réservé à Mac et qui n'est pas disponible pour iOS.

Je sais également qu'il existe une question similaire à celle-ci, mais elle n'a pas reçu de réponse. J'ai donc décidé d'essayer à nouveau et de voir si quelqu'un a créé un moyen de faire cela et, si oui, s'il peut le partager.

2 votes

La bibliothèque NSAttributedString-Additions-for-HTML a été renommée et intégrée dans un framework par le même auteur. Elle s'appelle désormais DTCoreText et comprend un ensemble de classes de mise en page Core Text. Vous pouvez la trouver sur aquí

300voto

pix Points 1343

Dans iOS 7, UIKit a ajouté une fonction initWithData:options:documentAttributes:error: qui permet d'initialiser un NSAttributedString en utilisant le langage HTML, par exemple :

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

Dans 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)

0 votes

Quelque chose de similaire pour iOS6 ?

0 votes

@Lirik Je pense qu'avec iOS6, la meilleure solution est la réponse de DTCoreText ci-dessus. Nous croisons les doigts en espérant que nos utilisateurs auront tous mis à jour d'ici le lancement ;)

31 votes

Pour une raison quelconque, l'option NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType fait que l'encodage prend beaucoup, beaucoup de temps :(

46voto

Ingve Points 775

Il y a un travail en cours complément open source à NSAttributedString par Oliver Drobnik sur Github. Il utilise NSScanner pour l'analyse HTML.

0 votes

Nécessite un déploiement minimum d'iOS 4.3 :( Néanmoins, très impressionnant.

3 votes

@Lirik Trop pour vous peut-être mais parfait pour quelqu'un d'autre, c'est-à-dire que votre commentaire n'est pas du tout utile.

3 votes

Veuillez noter que ce projet est open source et couvert par une licence BSD standard à 2 clauses. Cela signifie que vous devez mentionner Cocoanetics comme l'auteur original de ce code et reproduire le texte de la LICENCE dans votre application.

32voto

La création d'une NSAttributedString à partir de HTML doit être effectuée sur le thread principal !

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

Journal de bord de New Relic :

enter image description here

Vous trouverez ci-dessous une mise à jour sécurisé pour les threads Swift 2 String extension :

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 :

enter image description here

22voto

Mobile Dan Points 11

Extension de l'initialisateur Swift sur NSAttributedString

J'avais l'intention de l'ajouter en tant qu'extension de NSAttributedString plutôt que String . Je l'ai essayé en tant qu'extension statique et en tant qu'initialisateur. Je préfère l'initialisateur 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)

12voto

samwize Points 4144

Il s'agit d'un String écrite en Swift pour renvoyer une chaîne de caractères HTML sous forme de 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
    }
}

A utiliser,

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

Dans le texte ci-dessus, j'ai volontairement ajouté un code unicode \u2022 pour montrer qu'il rend correctement l'unicode.

Une question triviale : l'encodage par défaut que le NSAttributedString utilise est NSUTF16StringEncoding (pas UTF8 !).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X