Crash while decoding with NSCoder - ios

I have two model classes for saving data, I am getting crash while decoding the data.
The first class:
class User: NSObject,NSCoding, Mappable {
var authenticationToken: String?
var _id: String?
var email: String?
var profilePhoto: String?
var country: String?
var contactNo: String?
var occupation: String?
var aboutMe: String?
var role: RollType?
var createdAt: String?
var isActive: Bool?
var avg: Double?
var review: Review?
var subscribe: subscriptionType?
var isPayment: Bool?
var payment: Float?
var invoiceURL: String?
var firstName: String?
var lastName: String?
var password: String?
var pesaPal : [pesaPalData]?
required init?(map: Map) {
super.init()
mapping(map: map)
}
override init() {
super.init()
}
required init(coder aDecoder: NSCoder) {
super.init()
authenticationToken = aDecoder.decodeObject(forKey: "token") as? String
_id = aDecoder.decodeObject(forKey: "_id") as? String
email = aDecoder.decodeObject(forKey: "email") as? String
profilePhoto = aDecoder.decodeObject(forKey: "profilePhoto") as? String
country = aDecoder.decodeObject(forKey: "country") as? String
contactNo = aDecoder.decodeObject(forKey: "contactNo") as? String
occupation = aDecoder.decodeObject(forKey: "occupation") as? String
aboutMe = aDecoder.decodeObject(forKey: "aboutMe") as? String
role = RollType(rawValue: (aDecoder.decodeObject(forKey: "role") as! String))
createdAt = aDecoder.decodeObject(forKey: "createdAt") as? String
isActive = aDecoder.decodeObject(forKey: "isActive") as? Bool
subscribe = subscriptionType(rawValue: (aDecoder.decodeObject(forKey: "subscribe") as! String))
invoiceURL = aDecoder.decodeObject(forKey: "invoiceURL") as? String
isPayment = aDecoder.decodeObject(forKey: "isPayment") as? Bool
payment = aDecoder.decodeObject(forKey: "payment") as? Float
firstName = aDecoder.decodeObject(forKey: "firstName") as? String
lastName = aDecoder.decodeObject(forKey: "lastName") as? String
pesaPal = aDecoder.decodeObject(forKey: "pesaPal") as? [pesaPalData]
}
func encode(with aCoder: NSCoder) {
aCoder.encode(authenticationToken, forKey: "token")
aCoder.encode(_id, forKey: "_id")
aCoder.encode(email, forKey: "email")
aCoder.encode(profilePhoto, forKey: "profilePhoto")
aCoder.encode(country, forKey: "country")
aCoder.encode(contactNo, forKey: "contactNo")
aCoder.encode(occupation, forKey: "occupation")
aCoder.encode(aboutMe, forKey: "aboutMe")
aCoder.encode(role?.rawValue, forKey: "role")
aCoder.encode(createdAt, forKey: "createdAt")
aCoder.encode(isActive, forKey: "isActive")
aCoder.encode(subscribe?.rawValue, forKey: "subscribe")
aCoder.encode(isPayment, forKey: "isPayment")
aCoder.encode(payment, forKey: "payment")
aCoder.encode(invoiceURL, forKey: "invoiceURL")
aCoder.encode(firstName, forKey: "firstName")
aCoder.encode(lastName, forKey: "lastName")
aCoder.encode(pesaPal, forKey: "pesaPal")
}
func mapping(map: Map) {
_id <- map["_id"]
email <- map["email"]
profilePhoto <- map["profilePhoto"]
country <- map["country"]
contactNo <- map["contactNo"]
occupation <- map["occupation"]
aboutMe <- map["aboutMe"]
role <- (map["role"],EnumTransform<RollType>())
createdAt <- map["createdAt"]
isActive <- map["isActive"]
review <- map["review"]
avg <- map["avg"]
subscribe <- map["subscribe"]
isPayment <- map["isPayment"]
payment <- map["payment"]
invoiceURL <- map["invoiceURL"]
firstName <- map["firstName"]
lastName <- map["lastName"]
password <- map["password"]
pesaPal <- map["pesapalDetails"]
}
}
The second class:
class pesaPalData: NSObject, Mappable , NSCoding{
var payment1 : String?
var pesapalStatus : String?
var reference : String?
required init?(coder aDecoder: NSCoder) {
payment1 = aDecoder.value(forKey: "paymentPesa") as? String
pesapalStatus = aDecoder.value(forKey: "pesapalStatus") as? String
reference = aDecoder.value(forKey: "reference") as? String
}
required init?(map: Map) {
super.init()
self.mapping(map: map)
}
func encode(with aCoder: NSCoder) {
aCoder.encode(payment1, forKey: "paymentPesa")
aCoder.encode(pesapalStatus, forKey: "pesapalStatus")
aCoder.encode(reference, forKey: "reference")
}
func mapping(map: Map) {
payment1 <- map["payment"]
pesapalStatus <- map["pesapalStatus"]
reference <- map["reference"]
}
}
I am getting crash while decoding from the pespalData class :
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ valueForUndefinedKey:]:
this class is not key value coding-compliant for the key paymentPesa
Help would be appreciated about what's causing the crash,
Thanks

Aren’t you calling the wrong method on the decoder? You should be calling decodeObject(forKey:), not value(forKey:).

In your Encoding and Decoding you are using the key paymentPesa
but in your mapping you are using payment.
Maybe change mapping like this:
func mapping(map: Map) {
payment1 <- map["paymentPesa"]
pesapalStatus <- map["pesapalStatus"]
reference <- map["reference"]
}

Related

Unrecognized selector sent to instance while archiving nested custom object

I am trying to save the custom object that includes another custom object to UserDefault but I keep getting
'unrecognized selector sent to instance'
error.
I have implemented the NSCoding protocol to both the classes.
let encodedData: Data = NSKeyedArchiver.archivedData(withRootObject: details)
I am trying to archive RideDetails Class and save it to UserDefault.
I have done similar in another project which didn't include nested custom object and it worked fine. May be because of the nested object it didn't work. I couldn't figure it out.
DriverProfile Class
class DriverProfile: NSObject, NSCoding{
private var userId: Int
private var driverId:Int
private var firstName: String
private var lastName: String
private var phone: String
private var email:String?
private var location: CLLocation?
private var vehicleType: String
private var vehicleNo: String
private var rating:Double?
private var imageName:String?
init(userId: Int, driverId: Int, firstName:String, lastName: String, phone:String, email:String?, location:CLLocation?,vehicleType:String,vehicleNo:String,rating:Double?,imageName:String?) {
self.userId = userId
self.driverId = driverId
self.firstName = firstName
self.lastName = lastName
self.phone = phone
self.email = email
self.location = location
self.vehicleType = vehicleType
self.vehicleNo = vehicleNo
self.rating = rating
self.imageName = imageName
}
func encode(with aCoder: NSCoder) {
aCoder.encode(userId, forKey:"userId")
aCoder.encode(driverId, forKey:"driverId")
aCoder.encode(firstName, forKey:"firstName")
aCoder.encode(lastName, forKey:"lastName")
aCoder.encode(phone, forKey:"phone")
aCoder.encode(email, forKey:"email")
aCoder.encode(location, forKey:"location")
aCoder.encode(vehicleType, forKey:"vehicleType")
aCoder.encode(vehicleNo, forKey:"vehicleNo")
aCoder.encode(rating, forKey:"rating")
aCoder.encode(imageName, forKey:"imageName")
}
required init?(coder aDecoder: NSCoder) {
userId = aDecoder.decodeInteger(forKey: "userId")
driverId = aDecoder.decodeInteger(forKey: "driverId")
firstName = aDecoder.decodeObject(forKey: "firstName") as! String
lastName = aDecoder.decodeObject(forKey: "lastName") as! String
phone = aDecoder.decodeObject(forKey: "phone") as! String
email = aDecoder.decodeObject(forKey: "email") as? String
location = aDecoder.decodeObject(forKey: "location") as? CLLocation
vehicleType = aDecoder.decodeObject(forKey: "vehicleType") as! String
vehicleNo = aDecoder.decodeObject(forKey: "vehicleNo") as! String
rating = aDecoder.decodeObject(forKey: "rating") as? Double
imageName = aDecoder.decodeObject(forKey: "imageName") as? String
super.init()
}
}
RideDetails Class
class RideDetails: NSObject{
private var rideTime:String?
private var rideId:Int
private var driverProfile:DriverProfile
private var destinationLocation: CLLocation?
private var myLocation:CLLocation?
private var otpCode:String
private var trackRideURL:String
private var customerId:Int
private var extendedRange:Bool?
private var extendedRangePrice:Double?
init(rideTime:String?,rideId:Int,driverProfile:DriverProfile,destinationLocation:CLLocation?,myLocation:CLLocation?,otpCode:String,trackRideURL:String,customerId:Int,extendedRange:Bool?,extendedRangePrice:Double?) {
self.rideTime = rideTime
self.rideId = rideId
self.driverProfile = driverProfile
self.destinationLocation = destinationLocation
self.myLocation = myLocation
self.otpCode = otpCode
self.trackRideURL = trackRideURL
self.customerId = customerId
self.extendedRange = extendedRange
self.extendedRangePrice = extendedRangePrice
}
func encode(with aCoder: NSCoder) {
aCoder.encode(rideTime, forKey:"rideTime")
aCoder.encode(rideId, forKey:"rideId")
aCoder.encode(driverProfile, forKey:"driverProfile")
aCoder.encode(destinationLocation, forKey:"destinationLocation")
aCoder.encode(myLocation, forKey:"myLocation")
aCoder.encode(otpCode, forKey:"otpCode")
aCoder.encode(trackRideURL, forKey:"trackRideURL")
aCoder.encode(customerId, forKey:"customerId")
aCoder.encode(extendedRange, forKey:"extendedRange")
aCoder.encode(extendedRangePrice, forKey:"extendedRangePrice")
}
required init?(coder aDecoder: NSCoder) {
rideTime = aDecoder.decodeObject(forKey: "rideTime") as? String
rideId = aDecoder.decodeInteger(forKey: "rideId")
driverProfile = aDecoder.decodeObject(forKey: "driverProfile") as! DriverProfile
destinationLocation = aDecoder.decodeObject(forKey: "destinationLocation") as? CLLocation
myLocation = aDecoder.decodeObject(forKey: "myLocation") as? CLLocation
otpCode = aDecoder.decodeObject(forKey: "otpCode") as! String
trackRideURL = aDecoder.decodeObject(forKey: "trackRideURL") as! String
customerId = aDecoder.decodeInteger(forKey: "customerId")
extendedRange = aDecoder.decodeObject(forKey: "extendedRange") as? Bool
extendedRangePrice = aDecoder.decodeObject(forKey: "extendedRangePrice") as? Double
super.init()
}
}

NSKeyedArchiver.archivedData does not work in Swift 3 iOS

When try to encode my custom object in iOS swift get this error from Xcode 8.3
unrecognized selector sent to instance 0x60800166fe80
*** -[NSKeyedArchiver dealloc]: warning: NSKeyedArchiver deallocated without having had -finishEncoding called on it.
And my code like this:
import UIKit
import Foundation
class Place: NSObject {
func setCustomObject(CustomObject obj:Any,Key key:String) {
let encodedObject : Data = NSKeyedArchiver.archivedData(withRootObject: obj)
UserDefaults.standard.set(encodedObject, forKey: key)
}
}
Here's an example how to make an object to conform to NSCoding. Basically you need to provide implementation of two methods - required convenience init?(coder decoder: NSCoder) and encode(with aCoder: NSCoder)
class Book: NSObject, NSCoding {
var title: String?
var pageCount: Int?
// Memberwise initializer
init(title: String,pageCount: Int) {
self.title = title
self.pageCount = pageCount
}
// MARK: NSCoding
// Here you will try to initialize an object from archve using keys you did set in `encode` method.
required convenience init?(coder decoder: NSCoder) {
guard let title = decoder.decodeObject(forKey: "title") as? String else { return nil }
self.init(title: title, pageCount: decoder.decodeInteger(forKey: "pageCount"))
}
// Here you need to set properties to specific keys in archive
func encode(with aCoder: NSCoder) {
aCoder.encode(self.title, forKey: "title")
aCoder.encodeCInt(Int32(self.pageCount), forKey: "pageCount")
}
}
Also I would recommend changing your setCustomObject method to this:
func setCustomObject(obj:NSCoding, key:String) {
let encodedObject : Data = NSKeyedArchiver.archivedData(withRootObject: obj)
UserDefaults.standard.set(encodedObject, forKey: key)
}
This way compiler prevent you passing NSKeyedArchiver an object that does not conform to NSCoding protocol.
If you don't want to provide all properties in the init method you can use default values:
init(title : String? = nil, pageCount: Int? = nil){
self.title = title
self.pageCount = pageCount
}
Now you can just init your object without any properties. Like that Book()
Here is the solutions, you have to implement the two methods
Encode Method
func encode(with aCoder: NSCoder)
Decoding method
required init?(coder aDecoder: NSCoder)
Complete Example code
class User: NSObject , NSCoding
{
var userID : Int = 0
var name : String = ""
var firstName : String = ""
var lastName : String = ""
var username : String = ""
var email : String = ""
override init(){
super.init();
}
func encode(with aCoder: NSCoder) {
aCoder.encode(self.userID, forKey: "id");
aCoder.encode(self.firstName, forKey: "first_name");
aCoder.encode(self.lastName, forKey: "last_name");
aCoder.encode(self.name, forKey: "name");
aCoder.encode(self.username,forKey: "username");
aCoder.encode(self.email, forKey: "email");
}
required init?(coder aDecoder: NSCoder) {
super.init()
self.userID = aDecoder.decodeInteger(forKey: "id");
self.firstName = aDecoder.decodeObject(forKey: "first_name") as! String;
self.lastName = aDecoder.decodeObject(forKey: "last_name") as! String;
self.name = aDecoder.decodeObject(forKey: "name") as! String
self.username = aDecoder.decodeObject(forKey: "username") as! String
self.email = aDecoder.decodeObject(forKey: "email") as! String;
}
init(data : [String: AnyObject]) {
super.init()
self.userID = String.numberValue(data["user_id"]).intValue;
self.firstName = String.stringValue(data["first_name"]);
self.lastName = String.stringValue(data["last_name"]);
self.email = String.stringValue(data["email"]);
self.username = String.stringValue(data["user_name"]);
}
class func loadLoggedInUser() -> User {
if let archivedObject = UserDefaults.standard.object(forKey:"CurrentUserAcc"){
if let user = NSKeyedUnarchiver.unarchiveObject(with: (archivedObject as! NSData) as Data) as? User {
return user;
}
}
return User()
}
func saveUser(){
let archivedObject : NSData = NSKeyedArchiver.archivedData(withRootObject: self) as NSData
UserDefaults.standard.set(archivedObject, forKey: "CurrentUserAcc");
UserDefaults.standard.synchronize();
}
func deleteUser(){
UserDefaults.standard.set(nil, forKey: "CurrentUserAcc")
UserDefaults.standard.synchronize();
}
}

Saving Array of Struct with NSKeyedArchiver and Userdefault in which object conform to NSCoding

As a Protocol oriented programming concept, I have created my model with Struct.
I want to save Array of "Struct" into Userdefault. But I am having a problem in encode/decode of the array of this model.
Here is my model Struct
struct Room {
let name : String
let id : String
let booked : Bool
}
Here I created a extension like this
extension Room {
func decode() -> Room? {
let userClassObject = NSKeyedUnarchiver.unarchiveObject(withFile: RoomClass.path()) as? RoomClass
return userClassObject?.room
}
func encode() {
let personClassObject = RoomClass(room: self)
NSKeyedArchiver.archiveRootObject(personClassObject, toFile: RoomClass.path())
}
class RoomClass: NSObject, NSCoding {
var room : Room?
init(room: Room) {
self.room = room
super.init()
}
class func path() -> String {
let documentsPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).first
let path = documentsPath?.appending(("/Room"))
return path!
}
func encode(with aCoder: NSCoder) {
aCoder.encode(room!.name, forKey: "name")
aCoder.encode(room!.id, forKey: "Id")
aCoder.encode(room!.booked, forKey: "booked")
}
required init?(coder aDecoder: NSCoder) {
let _name = aDecoder.decodeObject(forKey: "name") as? String
let _id = aDecoder.decodeObject(forKey: "Id") as? String
let _booked = aDecoder.decodeBool(forKey: "booked")
room = Room(name: _name!, id: _id!, booked: _booked)
super.init()
}
}
}
When I am trying to save arrRoomList(a Array of Room objects) like this
self.saveRooms(arrayRooms: arrRoomList)
I got this error
[_SwiftValue encodeWithCoder:]: unrecognized selector sent to instance
I have also tried to encode each object first and then try to save them in default, then also it gives an error.
Can anyone please guide me how to encode/decode the array of Struct in Userdefaults in a proper way without converting it into Dictionary?
you can setup the struct to use NSKeyedArchiver directly like this:
struct Room {
let name : String
let id : String
let booked : Bool
}
extension Room {
func encode() -> Data {
let data = NSMutableData()
let archiver = NSKeyedArchiver(forWritingWith: data)
archiver.encode(name, forKey: "name")
archiver.encode(id, forKey: "id")
archiver.encode(booked, forKey: "booked")
archiver.finishEncoding()
return data as Data
}
init?(data: Data) {
let unarchiver = NSKeyedUnarchiver(forReadingWith: data)
defer {
unarchiver.finishDecoding()
}
guard let name = unarchiver.decodeObject(forKey: "name") as? String else { return nil }
guard let id = unarchiver.decodeObject(forKey: "id") as? String else { return nil }
booked = unarchiver.decodeBool(forKey: "booked")
self.name = name
self.id = id
}
}
to use with UserDefaults, call like this:
// to encode to data and save to user defaults
let room = Room(name: "asdf", id: "123", booked: true)
UserDefaults.standard.set(room.encode(), forKey: "room")
// to retrieve from user defaults
if let data = UserDefaults.standard.object(forKey: "room") as? Data {
let room = Room(data: data)
}
Can save/retrieve an array of rooms like this:
func saveRooms(arrayRooms: [Room]) {
let roomsData = arrayRooms.map { $0.encode() }
UserDefaults.standard.set(roomsData, forKey: "rooms")
}
func getRooms() -> [Room]? {
guard let roomsData = UserDefaults.standard.object(forKey: "rooms") as? [Data] else { return nil }
return roomsData.flatMap { return Room(data: $0) }
}
// save 2 rooms to user defaults
let roomA = Room(name: "A", id: "123", booked: true)
let roomB = Room(name: "B", id: "asdf", booked: false)
saveRooms(arrayRooms: [roomA, roomB])
// get the rooms
print(getRooms())
You can try Model like
class CardModel: NSObject
{
let name : String
let id : String
let booked : Bool
override init()
{
self.name = ""
self.id = ""
self.booked = false
}
required init(coder aDecoder: NSCoder)
{
self.name = aDecoder.decodeObject(forKey: "name") as! String
self.id = aDecoder.decodeObject(forKey: "id") as! String
self.booked = aDecoder.decodeObject(forKey: "booked") as! Bool
}
func encodeWithCoder(_ aCoder: NSCoder)
{
aCoder.encode(name, forKey: "name")
aCoder.encode(id, forKey: "id")
aCoder.encode(booked, forKey: "booked")
}
}
Use by Creating CardModel model Object
let objCardModel = CardModel()
objCardModel.name = "Shrikant"
objCardModel.id = "8"
objCardModel.booked = true
Access by object
let userName = objCardModel.name

Can't add data NSKeyedArchiver in NSUserDefauls Swift 3

I have a class Users. And I use NSKeyedArchiver add this in NSUserDefaults, but this does not work.
This is my code:
let encodedData = NSKeyedArchiver.archivedData(withRootObject: self.user) as Data
self.prefs.setValue(encodedData, forKey: "user")
Error: libc++abi.dylib: terminating with uncaught exception of type NSException
And this is my class Users
class Users : NSObject, NSCoding {
var token : String?
var username : String?
var phone : String?
var email: String?
var date : Date?
var language : String?
var age : Int?
override init() {
}
init(token : String, username : String, phone : String, email: String, date : Date, language : String, age : Int) {
self.token = token
self.username = username
self.phone = phone
self.email = email
self.date = date
self.language = language
self.age = age
}
required init(coder aDecoder: NSCoder) {
self.token = aDecoder.decodeObject(forKey: "token") as? String
self.username = aDecoder.decodeObject(forKey: "username") as? String
self.phone = aDecoder.decodeObject(forKey: "phone") as? String
self.email = aDecoder.decodeObject(forKey: "email") as? String
self.date = aDecoder.decodeObject(forKey: "date") as? Date
self.language = aDecoder.decodeObject(forKey: "language") as? String
self.age = aDecoder.decodeInteger(forKey: "age")
}
func encode(with aCoder: NSCoder) {
aCoder.encode(token, forKey:"token")
aCoder.encode(username, forKey:"username")
aCoder.encode(phone, forKey:"phone")
aCoder.encode(date, forKey:"date")
aCoder.encode(language, forKey:"language")
aCoder.encode(age, forKey:"age")
}
}

-[_SwiftValue encodeWithCoder:]: unrecognized selector sent to instance

Getting error when trying to utilize NSCoder
Player.swift:
class Player: NSObject, NSCoding {
private var _playerName: String!
private var _playerScore: Int!
private var _playerColor: PlayerColor! //PlayerColor is an enum
var playerName: String {
get {
return _playerName
}
set {
_playerName = newValue
}
}
var playerScore: Int {
get {
return _playerScore
}
set {
_playerScore = newValue
}
}
var playerColor: PlayerColor {
get {
return _playerColor
}
set {
_playerColor = newValue
}
}
init(playerName: String, playerScore: Int, playerColor: PlayerColor) {
_playerName = playerName
_playerScore = playerScore
_playerColor = playerColor
}
required convenience init(coder aDecoder: NSCoder) {
let name = aDecoder.decodeObject(forKey: "name") as! String
let score = aDecoder.decodeInteger(forKey: "score")
let color = aDecoder.decodeObject(forKey: "color") as! PlayerColor
self.init(playerName: name, playerScore: score, playerColor: color)
}
func encode(with aCoder: NSCoder){
aCoder.encode(playerName, forKey: "name")
aCoder.encode(playerScore, forKey: "score")
aCoder.encode(playerColor, forKey: "color")
}
}
in PlayerStore.swift:
// Storage Functions
func savePlayers(){
let encodedData = NSKeyedArchiver.archivedData(withRootObject: _playerArray) // _playerarray is a [Player] the very object I want to store/retrieve at will
defaults.set(encodedData, forKey: playerKeyForDefaults) //defaults is just var NSUserDefaults.standard
defaults.synchronize()
}
func loadPlayers(){
if let decoded = defaults.object(forKey: playerKeyForDefaults) as? NSData {
let array = NSKeyedUnarchiver.unarchiveObject(with: decoded as Data) as! [Player]
_playerArray = array
}
}
Here's the solution I implemented:
Player.swift:
import Foundation
class Player: NSObject, NSCoding {
private var name: String!
private var score: Int!
private var color: String!
var playerName: String {
get {
return name
}
set {
name = newValue
}
}
var playerScore: Int {
get {
return score
}
set {
score = newValue
}
}
var playerColor: String {
get {
return color
}
set {
color = newValue
}
}
init(playerName: String, playerScore: Int, playerColor: String) {
name = playerName
score = playerScore
color = playerColor
}
required convenience init(coder aDecoder: NSCoder) {
let name = aDecoder.decodeObject(forKey: "name") as! String
let score = aDecoder.decodeObject(forKey: "score") as! Int
let color = aDecoder.decodeObject(forKey: "color") as! String
self.init(playerName: name, playerScore: score, playerColor: color)
}
func encode(with aCoder: NSCoder){
aCoder.encode(name, forKey: "name")
aCoder.encode(score, forKey: "score")
aCoder.encode(color, forKey: "color")
}
}
PlayerStore.swift:
func savePlayers(){
let encodedData = NSKeyedArchiver.archivedData(withRootObject: _playerArray)
defaults.set(encodedData, forKey: playerKeyForDefaults)
}
func loadPlayers(){
if let decoded = defaults.object(forKey: playerKeyForDefaults) as? NSData {
let array = NSKeyedUnarchiver.unarchiveObject(with: decoded as Data) as! [Player]
_playerArray = array
}
}
You can also use this approach using Enum rawValue. It might help you to archivedData and unarchiveObject a complete model object.
Color Enum With Hex value:
enum PlayerColor: String {
case red = "#FF0000"
case silver = "#C0C0C0"
case gray = "#808080"
case black = "#000000"
var description: String {
return self.rawValue
}
}
import Foundation
class Player: NSObject, NSCoding {
private var name: String!
private var score: Int!
private var color: PlayerColor!
init(playerName: String, playerScore: Int, playerColor: PlayerColor) {
name = playerName
score = playerScore
color = playerColor
}
required convenience init(coder aDecoder: NSCoder) {
let name = aDecoder.decodeObject(forKey: "name") as! String
let score = aDecoder.decodeObject(forKey: "score") as! Int
if let value = aDecoder.decodeObject(forKey: "color") as? String{
color = PlayerColor(rawValue: value)
}
self.init(playerName: name, playerScore: score, playerColor: color)
}
func encode(with aCoder: NSCoder){
aCoder.encode(name, forKey: "name")
aCoder.encode(score, forKey: "score")
let value = color!.description
aCoder.encode(value, forKey: "color")
}
}

Resources