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?
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.
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) {
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.
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
Pour la chaîne HTML, NSAttributedString.DocumentType.html
est la bonne option.
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
}
}
}
Utilisation NSAttributedString.DocumentType.html
NSMutableAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html] , documentAttributes: nil)
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)