2015-01-16 35 views
5

我有自定義類名爲User的女巫符合NSCoding協議。但是,當我試圖存儲它NSUserDefaults的中我得到這個錯誤:在NSUserDefaults中存儲自定義對象時應用程序崩潰

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

而且這樣的警告:

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

User類:

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

更新 保存代碼:

let userKeyForDefaults = "apimanager.user" 


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

即使符合NSCoding,您也不能將自定義對象存儲到NSUserDefaults – vivek

+1

@vivek? – rabbitinspace

+0

我還沒有嘗試,但也許你的類必須基於NSObject?因此,類User:NSObject,NSCoding – Volker

回答

4

NSUserDefaults不支持所有對象,只是像NSString,NSDictionary,最重要的是NSData。這是NSCoding協議派上用場的地方。它允許我們將自定義對象轉換爲大塊NSData。要做到這一點,使用NSKeyedArchiver類把符合自定義對象NSCoding等效NSData

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

的文檔可以發現here和你正在尋找的方法是

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

要拿東西NSUserDefaults,用「反」類,NSKeyedUnarchiver。其適當的方法如下

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

下面是一個示例。

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

注:我可能混雜了一些optionals,但你得到了jist。 NSKeyedUnarchiver的文檔可以找到here

編輯:解決OP的問題就像正確使用NSKeyedArchiver和子類NSObject一樣簡單。

+0

仍然不能。但我不明白爲什麼? [截圖](http://i.imgur.com/NUZ4zsl.png) – rabbitinspace

+0

@devnikor你有沒有嘗試過我的解決方案和子類'NSObject',這是我能想到的唯一的東西。 –

+0

@devnikor檢查一下,它支持我的想法。 http://www.touch-code-magazine.com/does-not-implement-methodsignatureforselector-trouble-ahead/ –

相關問題