【问题标题】:Saving UIColor to and loading from NSUserDefaults将 UIColor 保存到 NSUserDefaults 并从中加载
【发布时间】:2010-11-19 12:38:04
【问题描述】:

UIColor 保存到NSUserDefaults 然后取出它的最简单方法是什么?

【问题讨论】:

标签: objective-c cocoa-touch nsuserdefaults uicolor


【解决方案1】:

一种方法可能是归档它(比如使用 NSColor,虽然我没有测试过):

NSData *colorData = [NSKeyedArchiver archivedDataWithRootObject:color];
[[NSUserDefaults standardUserDefaults] setObject:colorData forKey:@"myColor"];

然后把它拿回来:

NSData *colorData = [[NSUserDefaults standardUserDefaults] objectForKey:@"myColor"];
UIColor *color = [NSKeyedUnarchiver unarchiveObjectWithData:colorData];

【讨论】:

  • UIColor 实现了 NSCoding 协议,因此归档将起作用。
  • 此方法将颜色序列化为 315 字节的数据.. 似乎有点浪费。 Lifjoy 的回答所引用的 Erica Sadun 的 UIColor 类别似乎是一个更好的解决方案。
  • 这种方式还保存了与颜色关联的颜色配置文件。如果这对你来说不重要,那当然。
  • @Wevah 这似乎不适用于 CCColor,您对此有什么想法吗?
  • 在 Swift 中:var colorData:NSData = NSKeyedArchiver.archivedDataWithRootObject(color); defaults.setObject(colorData, forKey: "BackgroundColor");
【解决方案2】:

使用the accepted answer,您很快就会在您的代码中获得大量 NSKeyed 归档和取消归档。更简洁的解决方案是扩展 UserDefaults。这正是扩展的用途; UserDefaults 可能不知道 UIColor,因为 UIKit 和 Foundation 是不同的框架。

斯威夫特

extension UserDefaults {

    func color(forKey key: String) -> UIColor? {
        var color: UIColor?
        if let colorData = data(forKey: key) {
            color = NSKeyedUnarchiver.unarchiveObject(with: colorData) as? UIColor
        }
        return color
    }

    func set(_ value: UIColor?, forKey key: String) {
        var colorData: Data?
        if let color = value {
            colorData = NSKeyedArchiver.archivedData(withRootObject: color)
        }
        set(colorData, forKey: key)
    }

}

斯威夫特 4.2

extension UserDefaults {

    func color(forKey key: String) -> UIColor? {

        guard let colorData = data(forKey: key) else { return nil }

        do {
            return try NSKeyedUnarchiver.unarchivedObject(ofClass: UIColor.self, from: colorData)
        } catch let error {
            print("color error \(error.localizedDescription)")
            return nil
        }

    }

    func set(_ value: UIColor?, forKey key: String) {

        guard let color = value else { return }
        do {
            let data = try NSKeyedArchiver.archivedData(withRootObject: color, requiringSecureCoding: false)
            set(data, forKey: key)
        } catch let error {
            print("error color key data not saved \(error.localizedDescription)")
        }

    }

}

用法

UserDefaults.standard.set(UIColor.white, forKey: "white")
let whiteColor = UserDefaults.standard.color(forKey: "white")

这也可以在 Objective-C 中使用类别来完成。

我已将 Swift 文件添加为要点 here

【讨论】:

  • 您也可以在 Objective-C 中使用类别来执行此操作。
【解决方案3】:

我自己有答案

保存

const CGFloat  *components = CGColorGetComponents(pColor.CGColor);
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setFloat:components[0]  forKey:@"cr"];
[prefs setFloat:components[1]  forKey:@"cg"];
[prefs setFloat:components[2]  forKey:@"cb"];
[prefs setFloat:components[3]  forKey:@"ca"];

加载

NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
UIColor* tColor = [UIColor colorWithRed:[prefs floatForKey:@"cr"] green:[prefs floatForKey:@"cg"] blue:[prefs floatForKey:@"cb"] alpha:[prefs floatForKey:@"ca"]];

【讨论】:

  • 唯一可能出现的问题是如果底层 CGColor 不在 RGB 颜色空间中。如果您确定它将是 RGB,这可能是比存档更好的选择。
  • 除了 RGB 假设之外,一旦您要保留两种或更多颜色,此解决方案就会变得烦人。理想情况下,您希望将所有颜色信息存储在一个键下,而不是四个键下,然后编写一个通用的 get/set 函数。
【解决方案4】:

感谢Erica's UIColor category。我不太喜欢在首选项中保存 4 个浮点数,只想要一个条目。

因此,使用 Erica 的 UIColor 类别,我能够将 RGB 颜色与 NSString 相互转换,该 NSString 可以保存在首选项中。

// Save a color
NSString *theColorStr = [self.artistColor stringFromColor];
[[NSUserDefaults standardUserDefaults] setObject:theColorStr forKey:@"myColor"];

// Read a color
NSString *theColorStr = [[NSUserDefaults standardUserDefaults] objectForKey:@"myColor"];
if ([theColorStr length] > 0) {
    self.myColor = [UIColor colorWithString:theColorStr];
} else {
    self.myColor = [UIColor colorWithRed:88.0/255.0 green:151.0/255.0 blue:237.0/255.0 alpha:1.0];
}

【讨论】:

  • 查看[NSUserDefaults registerDefaults:] 以设置默认值(这样您在读取值时可以避免 if/else)。
  • UIColor-Expanded.m 和 UIColor-Expanded.h 文件可以在这里找到:github.com/ars/uicolor-utilities
【解决方案5】:

Swift 3,UserDefaults 扩展

extension UserDefaults {

    internal func color(forKey key: String) -> UIColor? {
        guard let colorData = data(forKey: key) else {
            return nil
        }

        return NSKeyedUnarchiver.unarchiveObject(with: colorData) as? UIColor
    }

    internal func setColor(_ color: UIColor?, forKey key: String) {
        let colorData: Data?
        if let color = color {
            colorData = NSKeyedArchiver.archivedData(withRootObject: color)
        }
        else {
            colorData = nil
        }

        set(colorData, forKey: key)
    }
}

使用示例

let colorKey = "favoriteColor"

UserDefaults.standard.setColor(UIColor.red, forKey: colorKey)
let favoriteColor = UserDefaults.standard.color(forKey: colorKey)

print("favoriteColor is red: '\(favoriteColor == UIColor.red)'")


此答案基于a previous answer。它已针对 Swift 3 进行了更新。

【讨论】:

    【解决方案6】:

    我需要在用户默认值中存储 UIColor 对象数组。如其他答案所述,想法是将UIColor 转换为数据并保存该数据。我已在UIColor 上进行了扩展:

    extension UIColor {
       func data() -> Data {
          return NSKeyedArchiver.archivedData(withRootObject: self)
       }
       class func color(withData data: Data) -> UIColor? {
          return NSKeyedUnarchiver.unarchiveObject(with: data) as? UIColor
       }
    }
    

    用法:

    fileprivate var savedColors: [UIColor]? {
        get {
            if let colorDataArray = UserDefaults.standard.array(forKey: Constants.savedColorsKey) as? [Data] {
                return colorDataArray.map { UIColor.color(withData: $0)! }
            }
            return nil
        }
        set {
            if let colorDataArray = newValue?.map({ $0.data() }) {
                UserDefaults.standard.set(colorDataArray, forKey: Constants.savedColorsKey)
            }
    
        }
    }
    

    【讨论】:

      【解决方案7】:

      斯威夫特

      private let colorPickerKey = "ColorPickerKey"
      
      var selectedColor: UIColor? {
          get {
              guard let colorData = UserDefaults.standard.object(forKey: colorPickerKey) as? Data,
                  let color = NSKeyedUnarchiver.unarchiveObject(with: colorData) as? UIColor else { return nil }
              return color
          } set {
              guard let newValue = newValue else {
                  UserDefaults.standard.removeObject(forKey: colorPickerKey)
                  return
              }
              let colorData = NSKeyedArchiver.archivedData(withRootObject: newValue)
              UserDefaults.standard.set(colorData, forKey: colorPickerKey)
          }
      }
      

      【讨论】:

        【解决方案8】:

        编辑 2: 我似乎找到了answer。查看 Erica Sadun 关于扩展 UIColor 的文章。

        编辑:此代码似乎不适用于 UIColor 对象。不知道为什么...

        这里有一些代码可以看看:

        将对象保存到 NSUserDefaults 中:

         NSUserDefaults *userDefaults =[NSUserDefaults standardUserDefaults];
        [userDefaults setObject:someColorObject forKey:@"myColor"];
        

        从 NSUserDefaults 读取对象:

        NSUserDefaults *userDefaults =[NSUserDefaults standardUserDefaults];
        UIColor *someColor = (UIColor *)[userDefaults objectForKey:@"myColor"];
        

        【讨论】:

        • 感谢您的帮助,但似乎 NSUserDefaults 无法保存 UIColor 对象
        • 嗯,让我试试我上面贴的代码——我只是凭记忆写的。
        • 查看我在帖子正文中链接到的文章
        • 这不起作用,因为 NSUserDefaults 只能存储属性列表对象:NSString、NSNumber、NSDate、NSData、NSArray 和 NSDictionary(其中所有键必须是字符串)。其他任何东西都必须编码为这些对象之一。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-13
        • 2013-04-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多