Как заставить UIFont соответствовать декодируемым - PullRequest
1 голос
/ 29 мая 2019

Я пытаюсь заставить UIFont соответствовать Decodable, но мне трудно.

В настоящее время у меня есть решение, в котором я обертываю UIFont в структуру Font следующим образом:

public struct Font: Decodable{
    let font: UIFont

    private enum CodingKeys: String, CodingKey {
        case size
        case font
    }

    public init(from decoder: Decoder){
        do{
            let values = try decoder.container(keyedBy: CodingKeys.self)
            font = UIFont(name: try values.decode(String.self, forKey: .font), size: try values.decode(CGFloat.self, forKey: .size))!
        } catch{
            fatalError("Font configuration error:\(error)")
        }
    }
}

Это работает, но мне кажется неуклюжим, поэтому вместо этого я попробовал:

final class Font: UIFont, Decodable{
    private enum CodingKeys: String, CodingKey {
        case size
        case font
    }

    convenience init(from decoder: Decoder)  {
        do{
            let values = try decoder.container(keyedBy: CodingKeys.self)
            super.init(name: try values.decode(String.self, forKey: .font), size: try values.decode(CGFloat.self, forKey: .size))
        } catch{
            fatalError("Font configuration error:\(error)")
        }
    }
}

Это, однако, не работает, потому что init(from decoder: Decoder) не может быть сбойным инициализатором, а UIFont.init(name: String, size: CGFloat) является сбойным инициализатором, а вызов неуспешного инициализации из не сбойного невозможен.

Любые предложениякак заставить UIFont соответствовать Decodable без упаковки, это высоко ценится.

1 Ответ

1 голос
/ 29 мая 2019

Я пишу на мобильный телефон, поэтому не могу попробовать этот фрагмент, но думаю, что это может сработать. Дайте мне знать, если это поможет.

final class Font: Codable {
let size: CGFloat
let name: String

var font: UIFont = UIFont.init()

init(s: CGFloat, n: String) {
    size = s
    name = n

    font = UIFont(name: name, size: size) ?? UIFont.systemFont(ofSize: size)
}

enum CodingKeys: String, CodingKey {
    case size
    case name
}

required init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)

    size = try container.decode(CGFloat.self, forKey: .size)
    name = try container.decode(String.self, forKey: .name)

    font = UIFont(name: name, size: size) ?? UIFont.systemFont(ofSize: size)
}

func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: CodingKeys.self)

    try container.encode(size, forKey: .size)
    try container.encode(name, forKey: .name)
}
}
...