Подтвердить что ты не робот

Невозможно преобразовать значение типа NSAttributedString.DocumentAttributeKey в .DocumentReadingOptionKey

Я нашел это расширение строки где-то в SO, которое позволяет мне превращать HTML-код в строку с атрибутами:

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

В Swift 3 он работал нормально, но с Swift 4 Xcode жалуется:

Невозможно преобразовать значение типа "NSAttributedString.DocumentAttributeKey" в ожидаемый тип ключа словаря "NSAttributedString.DocumentReadingOptionKey"

Как это исправить?

4b9b3361

Ответ 1

Вам нужно передать один из доступных параметров NSAttributedString DocumentType:


Документ на языке гипертекстовой разметки (HTML).

static let html: NSAttributedString.DocumentType

Простой текстовый документ.

static let plain: NSAttributedString.DocumentType

Документ в формате Rich Text.

static let rtf: NSAttributedString.DocumentType

Богатый текстовый формат с вложениями документа.

static let rtfd: NSAttributedString.DocumentType

В этом случае вам нужно будет передать первый (html) NSAttributedString.DocumentType.html

Поэтому расширение, обновленное до Swift 4, должно выглядеть так:

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
        }

    }
}

Тестирование детской площадки

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

Обсуждение Импортер HTML не должен вызываться из фонового потока (то есть словарь опций включает documentType со значением html). Он попытается синхронизироваться с основным потоком, потерпит неудачу и истечет время ожидания. Вызов его из основного потока работает (но все равно может истечь время ожидания, если HTML содержит ссылки на внешние ресурсы, чего следует избегать любой ценой). Механизм импорта HTML предназначен для реализации чего-то вроде разметки (то есть стилей текста, цветов и т.д.), А не для общего импорта HTML.

Ответ 2

Если это было после автоматического преобразования в Swift 4. Исправлено путем изменения с:

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

в

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

Ответ 3

Это работает для меня:

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

Если вы не добавляете

.characterEncoding: String.Encoding.utf8. rawValue

приложение выйдет из строя.

Ответ 4

Для строки HTML NSAttributedString.DocumentType.html является правильной опцией.

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
        }
    }
}

Ответ 5

swift 4: я не знаю, почему во всех ответах есть ошибка компилятора для меня. поэтому используйте это расширение:

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 ?? ""
    }
}

как использовать?

mylable.text = htmlVariable.html2String

Ответ 6

Используйте NSAttributedString.DocumentType.html

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

Ответ 7

Я использую NSAttributedStringKey и имел аналогичную ошибку "Не могу преобразовать значение типа" в Swift 4. В случае, если кто-то использует NSAttributedStringKey, приходит сюда, ища ответ, вот как я исправил:

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,]

И вот как я добавляю атрибут к тексту:

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