在NSUserDefaults中存储通用数组

时间:2016-06-13 07:45:16

标签: arrays swift generics nsuserdefaults

我正在尝试在NSUserDefaults中存储一个通用数组,但是我收到以下错误:Cannot convert value of type 'Array<T>' to expected argument type 'AnyObject?'

我该如何解决这个问题?

public class PropertyStore {   
    private let userDefaults = NSUserDefaults.standardUserDefaults()

    public func loadSet<T>(key: String) -> Set<T>? {
        guard let array = userDefaults.objectForKey(key) as? [T] else {
            return nil
        }

        return Set<T>(array)
    }

    public func saveSet<T>(key: String, value: Set<T>) {
        let array = Array(value)
        userDefaults.setObject(array, forKey: key) // <- ERROR
    }
}

2 个答案:

答案 0 :(得分:1)

就像@lucasD所说,T需要至少符合NSCoding。所以代码看起来像这样。

     public func saveSet<T: NSCoding>(key: String, value: Set<T>) {
       let array = Array(value)
       userDefaults.setObject(array, forKey: key)
    }

然而,由于以下原因,这不起作用:

   public func loadSet<T: NSCoding>(key: String) -> Set<T>? {
    guard let array = userDefaults.objectForKey(key) as? [T] else {
        return nil
    }

    return Set<T>(array)
   }

  let defaults = PropertyStore()
  defaults.saveSet("array", value: [1,2,3])
  ///defaults.loadSet<Int>("array")  ===> Cannot explicitly specialize a function
  ///defaults.loadSet("array")     ===> Cannot infer Type T
  //let a: Set<Int>? = defaults.loadSet("array")  ==> T cannot be inferred

loadSet类型T的情况下,无法正确推断T,因为据我所知,我们无法从外部指定它。我首先尝试返回NSObject或Set<AnyObject> or Set<NSCoding>,然后显式输入。如果有更好的方法让我知道。

您可以查看此SO帖子,了解更多有关泛型参数无法从外部进行专业化的原因。 SO Generics specialization

答案 1 :(得分:0)

您应该将T定义为NSCoding符合级别。因此,当您要存储数组时,您将存储一组NSKeyedArchiver.archiveDataWithRootObject()个结果。然后,要在Set<T>方法中返回loadSet,您应该unarchive所有对象:

let storedData = NSUserDefaults.standardUserDefaults. ...
return storedData.flatMap { return NSKeyedUnarchiver.unarchiveObjectWithData($0) }