I have a class
class Player {
var name = ""
func encodeWithCoder(encoder: NSCoder) {
encoder.encodeObject(name)
}
func initWithCoder(decoder: NSCoder) -> Player {
self.name = decoder.decodeObjectForKey("name") as String
return self
}
init(coder aDecoder: NSCoder!) {
self.name = aDecoder.decodeObjectForKey("name") as String
}
init(name: String) {
self.name = name
}
}
and i want to serialise it and save to user defaults.
First of all I'm not sure how to correctly write encoder and decoder. So for init i wrote two methods.
When i try to execute this code:
func saveUserData() {
let player1 = Player(name: "player1")
let myEncodedObject = NSKeyedArchiver.archivedDataWithRootObject(player1)
NSUserDefaults.standardUserDefaults().setObject(myEncodedObject, forKey: "player")
}
app crashes and i get this message:
*** NSForwarding: warning: object 0xebf0000 of class '_TtC6GameOn6Player' does not implement methodSignatureForSelector: -- trouble ahead
What do i do wrong?
To store them in UserDefaults, we need to implement or confirm Codable to the user-defined class or struct. Codable is a typealias of Decodable & Encodable protocols. It adds the functionality of Encoding and Decoding to the class or struct.
In Swift 4 you don't need NSCoding anymore! There is a new protocol called Codable
!
class Player: Codable {
var name = ""
init(name: String) {
self.name = name
}
}
And Codable
also supports Enums and Structs so you can rewrite your player class to a struct if you want!
struct Player: Codable {
let name: String
}
To save your player in Userdefaults:
let player = Player(name: "PlayerOne")
try? UserDefaults.standard.set(PropertyListEncoder().encode(player), forKey: "player")
Note: PropertyListEncoder() is a class from the framework Foundation
To Retrieve:
let encoded = UserDefault.standard.object(forKey: "player") as! Data
let storedPlayer = try! PropertyListDecoder().decode(Player.self, from: encoded)
For more information, read https://developer.apple.com/documentation/swift/codable
NSKeyedArchiver
will only work with Objective-C classes, not pure Swift classes. You can bridge your class to Objective-C by marking it with the @objc
attribute or by inheriting from an Objective-C class such as NSObject
.
See Using Swift with Cocoa and Objective-C for more information.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With