2016-06-13 9 views
-1

Ich versuche, ein generisches Array in NSUserDefaults zu speichern, aber ich erhalte den folgenden Fehler: Cannot convert value of type 'Array<T>' to expected argument type 'AnyObject?'.Speichern Sie generische Arrays in NSUserDefaults

Wie kann ich dieses Problem lösen?

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 
    } 
} 

Antwort

0

Sie sollten T als NSCoding konforme Klasse definieren. Wenn Sie also das Array speichern, speichern Sie ein Array von NSKeyedArchiver.archiveDataWithRootObject() Ergebnissen. Dann ein Set<T> im loadSet Methode zurückkehren, sollten Sie unarchive alle Objekte:

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

Aber wenn ich ein 'Set ' habe, wird das zum Beispiel 'Set ' nicht konform sein. – multiholle

+0

Versuchen Sie also, jedes 'T' zu akzeptieren und versuchen Sie den Typ von' T' in Ihrer Methode zu überprüfen –

1

Wie @lucasD sagte, muss T NSCoding atleast anzupassen. Also sieht der Code so aus.

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

Dies wird jedoch nicht aus vielen Gründen arbeiten wie:

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 

Im Falle von loadSet Typ T kann nicht richtig geschlossen werden, weil wir es von außen nicht angeben können, soweit ich weiß. Ich würde zuerst versuchen, NSObject oder Set<AnyObject> or Set<NSCoding> zurückzugeben und geben Sie es dann explizit ein. Lass mich wissen, ob es einen besseren Weg gibt.

Sie können sich diesen SO-Post ansehen, um weitere Informationen darüber zu erhalten, warum ein Generika-Parameter nicht von außen spezialisiert werden kann. SO Generics specialization