web-dev-qa-db-fra.com

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 a bien fonctionné 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?

35
LinusGeffarth

Vous devez passer l’une des options NSAttributedString DocumentType disponibles:


Document HTML (Hypertext Markup Language).

static let html: NSAttributedString.DocumentType

Document en texte brut.

static let plain: NSAttributedString.DocumentType

Document au format RTF.

static let rtf: NSAttributedString.DocumentType

Format de texte enrichi avec document de pièces jointes.

static let rtfd: NSAttributedString.DocumentType

Dans ce cas, vous devrez passer le premier (html) NSAttributedString.DocumentType.html

Donc l'extension mise à jour à 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
        }

    }
}

Test de terrain de jeu

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 L'importateur HTML ne doit pas être appelé depuis un fil d'arrière-plan (en d'autres termes, le dictionnaire d'options inclut le type de document document avec une valeur html). Il essaiera de se synchroniser avec le thread principal, échouera et expirera. L'appeler depuis le thread principal fonctionne (mais peut toujours expirer si le HTML contient des références à des ressources externes, ce qui devrait être évité à tout prix). Le mécanisme d'importation HTML est conçu pour implémenter quelque chose comme le démarquage (c'est-à-dire les styles de texte, les couleurs, etc.), pas pour l'importation HTML générale.

88
Leo Dabus

Après cette conversion automatique en Swift 4. a été corrigé en changeant de:

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

à:

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

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 .rawValue

l'application va planter.

12
hall.keskin

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

4
iman kazemayni

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
        }
    }
}
4
Suhit Patil

Utilisation NSAttributedString.DocumentType.html

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

J'utilise NSAttributedStringKey et j'avais une erreur similaire "Impossible de convertir la valeur de type" sur Swift 4.). Si quelqu'un utilisant NSAttributedStringKey vient chercher une réponse, voici comment j'ai corrigé:

let TextStroke: [NSAttributedStringKey : Any] = [
    NSAttributedStringKey(rawValue: NSAttributedStringKey.strokeColor.rawValue) : UIColor.black,
    NSAttributedStringKey(rawValue: NSAttributedStringKey.foregroundColor.rawValue) : UIColor.white,
    NSAttributedStringKey(rawValue: NSAttributedStringKey.strokeWidth.rawValue) : -6.0,]

Et voici comment j'ajoute l'attribut au texte:

myLabel.attributedText = NSAttributedString(string: myString, attributes: TextStroke)
0
tomDev