39 votes

Impossible de convertir la valeur de type NSAttributedString.DocumentAttributeKey en .DocumentReadingOptionKey

J'ai trouvé cette extension de chaîne quelque part sur SO qui me permet de transformer le code html en chaîne attribuée:

 func html2AttributedString() -> NSAttributedString {
    return try! NSAttributedString(data: self.data(using: String.Encoding.unicode, allowLossyConversion: true)!, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil)
}
 

Cela fonctionnait bien dans Swift 3, mais avec Swift 4, Xcode se plaint:

Impossible de convertir la valeur de type 'NSAttributedString.DocumentAttributeKey' en type de clé de dictionnaire attendu 'NSAttributedString.DocumentReadingOptionKey'

Comment puis-je réparer ça?

93voto

Leo Dabus Points 122890

Vous avez besoin de passer l'un des NSAttributedString DocumentType options:


HTML (Hypertext Markup Language) dans le document.

static let html: NSAttributedString.DocumentType

Documents en texte brut.

static let plain: NSAttributedString.DocumentType

Rich text format de document.

static let rtf: NSAttributedString.DocumentType

Format de texte enrichi avec des pièces jointes de documents.

static let rtfd: NSAttributedString.DocumentType

Dans ce cas, vous aurez besoin de passer le premier (html) NSAttributedString.DocumentType.html

Ainsi, l'extension mise à jour de Swift 4 devrait ressembler à ceci:

extension NSAttributedString {
    convenience init(data: Data, documentType: DocumentType, encoding: String.Encoding = .utf8) throws {
        try self.init(data: data,
                      options: [.documentType: documentType,
                                .characterEncoding: encoding.rawValue],
                      documentAttributes: nil)
    }
    convenience init(html data: Data) throws {
        try self.init(data: data, documentType: .html)
    }
    convenience init(txt data: Data) throws {
        try self.init(data: data, documentType: .plain)
    }
    convenience init(rtf data: Data) throws {
        try self.init(data: data, documentType: .rtf)
    }
    convenience init(rtfd data: Data) throws {
        try self.init(data: data, documentType: .rtfd)
    }
}

extension StringProtocol {
    var data: Data { return Data(utf8) }
    var htmlToAttributedString: NSAttributedString? {
        do {
            return try .init(html: data)
        } catch {
            print("html error:", error)
            return nil
        }
    }
    var htmlDataToString: String? {
        return htmlToAttributedString?.string
    }
}

extension Data {
    var htmlToAttributedString: NSAttributedString? {
        do {
            return try .init(html: self)
        } catch {
            print("html error:", error)
            return nil
        }

    }
}

Aire De Jeux De Tests

let htmlString = "<style type=\"text/css\">#red{color:#F00}#green{color:#0F0}#blue{color: #00F; font-weight: Bold; font-size: 32}</style><span id=\"red\" >Red</span><span id=\"green\" > Green </span><span id=\"blue\">Blue</span>"

let htmlData = Data(htmlString.utf8)

htmlString.htmlToAttributedString
htmlData.htmlToAttributedString

Discussion Le code HTML de l'importateur ne devrait pas être appelée à partir d'un arrière-plan thread (qui est, les options dictionnaire comprend documentType avec un la valeur html). Il va essayer de se synchroniser avec le thread principal, échouer, et le temps. L'appelant depuis le thread principal fonctionne (mais peut encore le temps si le code HTML contient des références à des ressources externes, qui devrait être évitée à tous les frais). L'importation HTML mécanisme est destiné pour la mise en œuvre de quelque chose comme markdown (qui est, les styles de texte, les couleurs, etc), et non pas général d'importation HTML

23voto

Si cela avait eu lieu après la conversion automatique en Swift 4. A été corrigé en passant de:

 NSMutableAttributedString(data: data, 
   options: [NSAttributedString.DocumentAttributeKey.documentType : NSAttributedString.DocumentType.html], 
   documentAttributes: nil)
 

à:

 NSMutableAttributedString(data: data,
   options: [.documentType : NSAttributedString.DocumentType.html],
   documentAttributes: nil) {
 

14voto

hall.keskin Points 141

Cela fonctionne pour moi:

 let attrStr = try! NSAttributedString(
    data: modifiedFont.data(using: .unicode, allowLossyConversion: true)!,
    options:[.documentType: NSAttributedString.DocumentType.html,
    .characterEncoding: String.Encoding.utf8.rawValue],
    documentAttributes: nil)
 

Si vous n'ajoutez pas

.characterEncoding: String.Encoding.utf8. valeur brute

l'application va planter.

7voto

iman kazemayni Points 470

swift 4 : je ne sais pas pourquoi mais toutes les réponses ont une erreur de compilation pour moi. donc j'utilise cette extension:

 extension String {
    var html2AttributedString: NSAttributedString? {
        do {
            return try NSAttributedString(data: data(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue))!,
                                          options: [.documentType: NSAttributedString.DocumentType.html,
                                                    .characterEncoding: String.Encoding.utf8.rawValue],
                                          documentAttributes: nil)
        } catch {
            print("error: ", error)
            return nil
        }
    }
    var html2String: String {
        return html2AttributedString?.string ?? ""
    }
}
 

comment utiliser ?

mylable.text = htmlVariable.html2String

4voto

Suhit Patil Points 6334

Pour la chaîne HTML, NSAttributedString.DocumentType.html est la bonne option.

Swift 4

 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: [
                     NSAttributedString.documentType: NSAttributedString.DocumentType.html,
                     NSAttributedString.characterEncoding: String.Encoding.utf8.rawValue
                    ], documentAttributes: nil)
        } catch {
            print(error.localizedDescription)
            return nil
        }
    }
}
 

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