2015-05-25 5 views
1

Как я могу хранить UIColor в CoreData без потерь на 64 бит? На 32 бит возвращается правильный UIColor.Магазин UIColor в CoreData

CoreData установка

  • тип атрибута: трансформер
  • NSManagedObject подкласс объекта: @NSManaged уаг цвет: 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-битном уровне все прекрасно, и сравнение цветов успешно завершено.

+0

Ни 32-разрядные, ни 64-разрядные поплавки могут сохранить номер '0.2' точно. Сравнение чисел с плавающей запятой с '==' в большинстве случаев является плохим. –

+0

Попробовали сохранить значения цвета в Hex вместо этого, чтобы избежать проблемы точности. –

+1

Как вы архивируете UIColor? делать == с float/double никогда не умная идея! Посмотрите на http://stackoverflow.com/questions/1275662/saving-uicolor-to-and-loading-from-nsuserdefaults – Volker

ответ

2

Назначьте NSKeyedArchiver.archivedDataWithRootObject(color) переменной данных и сохраните ее вместо хранилища данных Core.

Чтобы прочитать данные, просто присвойте NSKeyedUnarchiver.unarchiveObjectWithData(colorData) цветовой переменной.


В случае, если вам интересно, как сравнивать поплавки в любом случае, вы всегда можете обратиться к this.

+1

Я думаю, что среда выполнения Core Data автоматически выполняет эти преобразования, если атрибут определяется как «Transformable». - И я не уверен, что это решает проблемы с 32-битными и 64-битными с плавающей точкой, о которых идет речь. –

+0

Вы не должны сравнивать поплавки напрямую в любом случае. 64-бит имеет более высокую точность, но округляется при сохранении в хранилище данных, оставляя при извлечении другое значение. Используйте epsilon :) – Schemetrical

+0

Я действительно сравниваю объекты UIColor с цветом == colorRetrievedFromCoreData. Кажется, что проблема с округлением CoreData. Это можно обойти, как вы сказали, путем хранения его как NSData, содержащего закодированную форму объекта UIColor. –

1

Это решило мою проблему:

  1. набор CoreData имя атрибута для моего пользовательского NSValueTransformer подкласса: MQColorTransformer

  2. реализованы следующие 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 
    } 
} 
+2

Обратите внимание, что (если я не ошибаюсь) это представление не является независимым от устройства. Если цвет архивируется на 32-битном устройстве и извлекается на 64-битном устройстве (или наоборот), результат будет неправильным. –

+0

Вы понимаете, что для первой функции вы можете «вернуть NSKeyedArchiver.archivedDataWithRootObject (цвет)» и избавиться от остальной части кода. Для второй функции вы можете «вернуть NSKeyedUnarchiver.unarchiveObjectWithData (данные)» и избавиться от остальной части кода. Это гораздо более элегантное решение вместо получения цветовых компонентов. – Schemetrical

+0

@Schemetrical: Это не работает, потому что сравнение снова не выполняется на 64 бит. –

Смежные вопросы