Ошибка использования Codable для NSAttributedString

Я пытаюсь реализовать Codable для класса, который содержит NSAttributedString, но я получаю ошибки во время компиляции:

try container.encode(str, forKey: .str)

ошибка неоднозначная ссылка на член 'кодировать (_:forKey:)'

а также

str = try container.decode(NSMutableAttributedString.self, forKey: .str)

ошибка: никакие кандидаты 'декодирования' не производят ожидаемый контекстный тип 'NSAttributedString'

Я могу обойти это, используя NSData из строки, но думал, что это должно работать, я бы подумал

class Text : Codable {
    var str : NSAttributedString

    enum CodingKeys: String, CodingKey {
        case str
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(str, forKey: .str). <-- error ambiguous reference to member 'encode(_:forKey:)'
    }

    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        str = try container.decode(NSMutableAttributedString.self, forKey: .str)  <-- error: No 'decode' candidates produce the expected contextual type 'NSAttributedString'
    }
}

2 ответа

NSAttributedString не соответствует Codable так что вы не можете сделать это напрямую.

Если вы просто хотите сохранить данные, вы можете реализовать простую обертку вокруг вашей атрибутной строки, которая соответствует Codable, и использовать ее в своем классе данных. Это довольно просто, так как вы можете преобразовать атрибутивную строку в Data с помощью data(from:documentAttributes) при кодировании. При декодировании вы сначала читаете данные, а затем инициализируете приписанную строку, используя init(data:options:documentAttributes:), Он поддерживает различные форматы данных, включая HTML, RTF и Microsoft Word.

Не поддавайтесь искушению добавить соответствие Codable для NSAttributedString в расширении. Это вызовет проблемы, когда Apple добавит это соответствие или вы добавите другую библиотеку, которая делает это.

С другой стороны, если вам это нужно для связи с сервером или какой-либо другой программой, вам необходимо точно соответствовать требуемому формату данных. Если вам нужна только простая строка, вам, вероятно, вообще не следует использовать NSAttributedString. Если это какой-то другой формат, например, уценка, вы можете реализовать оболочку, которая выполняет необходимые преобразования.

Если вы хотите декодировать и кодировать только текстовый контент и конвертировать его обратно из / в NS(Mutual)AttributedString Вы можете попробовать что-то вроде этого:

class Text : Codable {
var str : NSMutableAttributedString?

enum CodingKeys: String, CodingKey {
    case str
}

func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: CodingKeys.self)
    try? container.encode(str?.string, forKey: .str)
}

required init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    if let content =  try? container.decode(String.self, forKey: .str){
        str = NSMutableAttributedString(string: content)
        // ADD any attributes here if required...
    }
  }
}
Другие вопросы по тегам