2015-05-25 63 views
1

如何存储UIColor在CoreData上没有丢失64位? 在32位上返回正确的UIColor。在CoreData中存储UIColor

CoreData设置

  • 属性类型:变形的
  • NSManagedObject子类物业:@NSManaged VAR颜色:的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位:在32位

0.20000000298023224 

输出红色:

0.199999928 

而来的问题

颜色比较,使用==,失败在64位,因为这些值略有不同。在32位一切都很好,颜色比较成功。

+0

既不32位也不64位浮点数可以存储'数0.2'准确。在大多数情况下,将浮点数与'=='比较是不好的。 –

+0

已尝试保存十六进制颜色值,而不是完全避免精度问题。 –

+1

你是如何归档UIColor的?用float/double来做==绝不是一个聪明的主意!看看http://stackoverflow.com/questions/1275662/saving-uicolor-to-and-loading-from-nsuserdefaults – Volker

回答

2

NSKeyedArchiver.archivedDataWithRootObject(color)赋值给一个数据变量,并将其保存到您的Core Data存储中。

要读取数据,只需将NSKeyedUnarchiver.unarchiveObjectWithData(colorData)分配给颜色变量。


如果你想知道如何反正比较浮,你总是可以参考this

+1

我认为如果该属性被定义为“Transformable”,Core Data运行时会自动执行这些转换。 - 我不确定这是否解决了这个问题所涉及的32位和64位浮点问题。 –

+0

反正你不应该直接比较花车。 64位具有更高的精度,但在保存到数据存储区时被舍入,取出时保留不同的值。使用epsilon :) – Schemetrical

+0

我用颜色比较UIColor对象== colorRetrievedFromCoreData。四舍五入的CoreData似乎是问题所在。正如您所建议的那样,这可以通过将其存储为NSData(包含UIColor对象的编码形式)来绕过。 –

1

这解决了我的问题:

  1. 集CoreData属性名称到我的自定义NSValueTransformer子类:MQColorTransformer

  2. 实施了以下NSValueTransformer子类(这也是转换的UIColor到NSData的,像Schemeually建议,但它的优点是我仍然可以将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(color)'并摆脱其余的代码。对于第二个函数,您可以'返回NSKeyedUnarchiver.unarchiveObjectWithData(data)'并摆脱其余的代码。它是一个更加优雅的解决方案,而不是检索颜色组件。 – Schemetrical

+0

@Schemetrical:这不起作用,因为比较再次在64位上失败。 –