2015-01-16 11 views
5

Ho una classe personalizzata denominata User conforme al protocollo NSCoding. Ma quando sto cercando di conservarlo in NSUserDefaults ottengo questo errore:L'app si arresta in modo anomalo durante la memorizzazione di un oggetto personalizzato in NSUserDefaults

Property list invalid for format: 200 
(property lists cannot contain objects of type 'CFType') 

E questo avvertimento:

NSForwarding: warning: object 0x7f816a681110 of class 'Shikimori.User' 
does not implement methodSignatureForSelector: -- trouble ahead 
Unrecognized selector -[Shikimori.User _copyDescription] 

User classe:

class User: NSCoding { 

private enum CoderKeys: String { 
    case ID = "user.id" 
    case Username = "user.username" 
    case Email = "user.email" 
    case Avatar = "user.avatar" 
} 

let id: Int 
let username: String 
let email: String 
let avatar: String 

init(id: Int, username: String, email: String, avatar: String) { 
    self.id = id 
    self.username = username 
    self.email = email 
    self.avatar = avatar 
} 

required init(coder aDecoder: NSCoder) { 
    id = aDecoder.decodeIntegerForKey(CoderKeys.ID.rawValue) 
    username = aDecoder.decodeObjectForKey(CoderKeys.Username.rawValue) as String 
    email = aDecoder.decodeObjectForKey(CoderKeys.Email.rawValue) as String 
    avatar = aDecoder.decodeObjectForKey(CoderKeys.Avatar.rawValue) as String 
} 

func encodeWithCoder(aCoder: NSCoder) { 
    aCoder.encodeInteger(id, forKey: CoderKeys.ID.rawValue) 
    aCoder.encodeObject(username as NSString, forKey: CoderKeys.Username.rawValue) 
    aCoder.encodeObject(email as NSString, forKey: CoderKeys.Email.rawValue) 
    aCoder.encodeObject(avatar as NSString, forKey: CoderKeys.Avatar.rawValue) 
} 
} 

Aggiornamento codice di salvataggio :

let userKeyForDefaults = "apimanager.user" 


let defaults = NSUserDefaults.standardUserDefaults() 
defaults.setObject(user, forKey: self.userKeyForDefaults) 
+1

non è possibile archiviare oggetti personalizzati in NSUserDefaults – vivek

+1

@ vivek, anche se è conforme a NSCoding? – rabbitinspace

+0

non ho provato, ma forse la tua classe deve basarsi su NSObject? Quindi utente di classe: NSObject, NSCoding – Volker

risposta

4

NSUserDefaults non supporta tutti gli oggetti, solo cose come NSString, NSDictionary e, soprattutto, NSData. È qui che il protocollo NSCoding è utile. Ci consente di trasformare oggetti personalizzati in blocchi di NSData. Per fare questo, utilizzare la classe NSKeyedArchiver di trasformare un oggetto personalizzato che è conforme alle NSCoding agli equivalenti NSData

let obj = User() 
let data = NSKeyedArchiver. archivedDataWithRootObject(obj) 
/// Now you can store data 

La documentazione può essere trovato here ed il metodo che si sta cercando è

class func archivedDataWithRootObject(_ rootObject: AnyObject) -> NSData 

Per get things out di NSUserDefaults, utilizzare la classe "inversa", NSKeyedUnarchiver. Il suo metodo appropriato è il seguente

class func unarchiveObjectWithData(_ data: NSData) -> AnyObject? 

Ecco un esempio.

let data = NSUserDefaults.standardUserDefaults().objectForKey("somekey") 
let obj = NSKeyedUnarchiver. unarchiveObjectWithData(data) as User? 

Nota: potrei aver mescolato alcuni optionals, ma si ottiene il jist. La documentazione per NSKeyedUnarchiver può essere trovata here.

Modifica: risolvere il problema dell'OP era semplice come utilizzare correttamente NSKeyedArchiver e sottoclasse NSObject.

+0

Non è ancora possibile. Ma non capisco perché? [screenshot] (http://i.imgur.com/NUZ4zsl.png) – rabbitinspace

+0

@devnikor Hai provato la mia soluzione e la sottoclasse 'NSObject', questa è l'unica cosa che riesco a pensare. –

+0

@devnikor Controlla questo, sostiene il mio pensiero. http://www.touch-code-magazine.com/does-not-implement-methodsignatureforselector-trouble-ahead/ –

Problemi correlati