Делаем UIColor Codable - в соответствии с протоколом 'Encodable' - PullRequest
0 голосов
/ 05 июля 2019

У меня проблемы с кодированием и загрузкой преобразуемых цветовых данных из списка, который без проблем загружался из кода.

В расширении UIColor у меня ограниченное количество доступных цветов в структуре плюс мой кодер и декодер.

extension UIColor
{
struct Words
{
    static let verb = UIColor(netHex: 0xff0000)
    static let noun = UIColor.blue
    static let subject = UIColor(netHex: 0x0000ff)
    static let object = UIColor(netHex: 0x1e5900)
    static let indirectObject = UIColor(netHex: 0x369d01)
    static let genitive = UIColor(netHex: 0x783f04)
    static let article = UIColor(netHex: 0xff6500)
    static let adjective = UIColor(netHex: 0x9900ff)
    static let adverb = UIColor(netHex: 0xff00ff)
    static let generic = UIColor(netHex: 0x70747a)
}

class func color(data:Data) -> UIColor? {
    return try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? UIColor
}

func encode() -> Data? {
    return try? NSKeyedArchiver.archivedData(withRootObject: self, requiringSecureCoding: false)
}
}

В моей модели кода (это работает), я просто определил текстовое значение цвета:

var color1: String?
... 
color1 = subject // etc

И в методе закодированные данные загружаются в БД:

let myColorData = myColor1.encode()

И затем в представлении коллекцииcellForItemAt indexPath, я могу получить доступ к данным цвета, которые я использую для атрибута текста (не показан).

let color1 = UIColor.color(data: cellData.color1 as! Data)

Проблема возникает, когда вместо загрузки данных из кода я загружаю их из списка pList.Кажется, что данные загружаются в Core Data, но приложение все равно падает, с ошибкой:

  • Невозможно привести значение типа 'NSTaggedPointerString' (0x108cc0560) к 'UIColor'

Я думаю, это означает, что UIColor не кодируется (?), Хотя кажется, что он загружает что-то «blob» в БД.

Если я следую совету Сделайте UIColor Codable и тому подобное, но я получаю сообщение об ошибке.

  • Ссылка на метод экземпляра 'encode (to :)' на 'Optional' требует, чтобы 'UIColor' соответствовал 'Encodable'.

Полагаю, мне нужно сделать мою структуру Words: Codable, но я не уверен, что это правда, и что требуется для этого.

Может кто-нибудь подсказать, что мне нужно сделать?в этом случае, как сделать кодировку UIColor так, как мне нужно?

1 Ответ

1 голос
/ 05 июля 2019

Почему вы хотите UIColor дополнительно соответствовать Codable?Он уже соответствует NSSecureCoding, поэтому по умолчанию он сериализуем Data.

И даже с вашей реализацией вы можете кодировать цвет

let encoded = UIColor.Words.adverb.encode()!

и декодировать его

let color = UIColor.color(data: encoded)

В частности, в Core Data вы можете использовать вычисленные свойства для преобразования поддерживаемого типа в неподдерживаемый и наоборот.

Моя рекомендация для Core Data - сохранить цвет как Int32 (шестнадцатеричное представление) или как (hex) String


Это реализация, которую я использую в Core Data, расширение для преобразования цвета в шестнадцатеричную строку

extension UIColor {

    private func float2String(_ float : CGFloat) -> String {
        return String(format:"%02X", Int(round(float * 255)))
    }

    var hex : String {
        var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0
        getRed(&red, green: &green, blue: &blue, alpha: nil)
        return "#" + float2String(red) + float2String(green) + float2String(blue)
    }

    convenience init(hex : String) {
        let hex = hex.hasPrefix("#") ? String(hex.dropFirst()) : hex
        if hex.count == 6, hex.range(of: "[^0-9A-Fa-f]", options: .regularExpression) == nil {
            let chars = Array(hex)
            let numbers = stride(from: 0, to: chars.count, by: 2).map() {
                CGFloat(strtoul(String(chars[$0 ..< min($0 + 2, chars.count)]), nil, 16))
            }
            self.init(red: numbers[0] / 255, green: numbers[1] / 255, blue: numbers[2] / 255, alpha: 1.0)
        } else {
            self.init(white: 1.0, alpha: 1.0)
        }
    }
}

исоответствующая часть NSManagedObject подкласса

@NSManaged public var hexColor: String


var color : UIColor {
    get { return UIColor(hex: hexColor) }
    set { hexColor = newValue.hex }
}
...