Хранить UIColor в CoreData
Как я могу хранить UIColor в CoreData без потерь на 64 бит? На 32 бит возвращается правильный UIColor.
Настройка CoreData
- тип атрибута: трансформируемый
- Свойство подкласса NSManagedObject: @NSManaged var color: UIColor?
Перед сохранением значения цвета
color.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
например, красный на 64-битной:
0.20000000000000018
красный вывод на 32 бит
0.199999928
После того, как цвет получен из CoreData
color.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
например, красный на 64-битной:
0.20000000298023224
красный вывод на 32 бит:
0.199999928
Результирующая проблема
Сравнение цветов с использованием == завершается неудачно на 64-битной, потому что значения немного отличаются. На 32-битной все хорошо, и сравнение цветов успешно.
3 ответа
Приписывать NSKeyedArchiver.archivedDataWithRootObject(color)
в переменную данных и сохраните ее в хранилище Core Data.
Чтобы прочитать данные, просто назначьте NSKeyedUnarchiver.unarchiveObjectWithData(colorData)
в цветовую переменную.
Если вам интересно, как сравнить поплавки, вы всегда можете обратиться к этому.
Это решило мою проблему:
установить имя атрибута CoreData для моего пользовательского подкласса NSValueTransformer: MQColorTransformer
реализовал следующий подкласс NSValueTransformer (который также преобразует UIColor в NSData, как предложил Schemetrical, но у него есть преимущество в том, что я все еще могу назначить UIColor своему свойству цвета, а NSValueTransformer позаботится о преобразовании за кулисами):
NSValueTransformer подкласс
import Foundation
import UIKit
@objc(MQColorTransformer) class MQColorTransformer: NSValueTransformer {
override class func transformedValueClass() -> AnyClass{
return NSData.classForCoder()
}
override func transformedValue(value: AnyObject!) -> AnyObject {
// Transform UIColor to NSData
let color = value as! UIColor
var red: CGFloat = 0
var green: CGFloat = 0
var blue: CGFloat = 0
var alpha: CGFloat = 0
color.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
var components:[CGFloat] = [red, green, blue, alpha]
let dataFromColors = NSData(bytes: components,
length: sizeofValue(components)*components.count)
return dataFromColors
}
override func reverseTransformedValue(value: AnyObject!) -> AnyObject {
// Transform NSData to UIColor
let data = value as! NSData
var components = [CGFloat](count: 4, repeatedValue:0)
var length=sizeofValue(components)
data.getBytes(&components, length: length * components.count)
let color = UIColor(red: components[0],
green: components[1],
blue: components[2],
alpha: components[3])
return color
}
}
Swift 5.7, минимальная цель развертывания iOS 11
import UIKit
final class ColorAttributeTransformer: ValueTransformer {
override class func transformedValueClass() -> AnyClass {
NSData.self
}
override func transformedValue(_ value: Any?) -> Any? {
let color = value as! UIColor
return NSKeyedArchiver.archivedData(withRootObject: color)
}
override func reverseTransformedValue(_ value: Any?) -> Any? {
let data = value as! Data
return NSKeyedUnarchiver.unarchiveObject(with: data)
}
}
Имейте в виду, что Xcode выполняет в консоли:'NSKeyedUnarchiveFromData' should not be used to for un-archiving and will be removed in a future release
.