Unrecognized selector sent to instance while archiving nested custom object - ios

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

Related

Crash while decoding with NSCoder

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

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

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

NSCoding custom object child array not persisting

I have two classes : Contact and Bill. Contact has an array of type Bill.
When I persist using NSKeyedArchiver my contacts persist just fine, however, it does not persist the Bill array.
Each time I add a a Bill or a Contact I call the insertNewObject() method in persist.
Here are my classes :
/* Persist.swift */
import Foundation
class Persist {
static let sharedInstance = Persist()
let delegate = UIApplication.sharedApplication().delegate as! AppDelegate
var contactsFilePath : String {
let manager = NSFileManager.defaultManager()
let url = manager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first! as NSURL
return url.URLByAppendingPathComponent("\(delegate.userId):objectsArrayz").path!
}
func insertNewObject(){
NSKeyedArchiver.archiveRootObject(delegate.contacts!, toFile: contactsFilePath)
}
func retrieveContracts(){
if let array = NSKeyedUnarchiver.unarchiveObjectWithFile(contactsFilePath) as? [Contact] {
delegate.contacts = array
}
}
func deleteContact(rowNum : Int){
delegate.contacts!.removeAtIndex(rowNum)
NSKeyedArchiver.archiveRootObject(delegate.contacts!, toFile: contactsFilePath)
}
/* Contact.swift */
import Foundation
class Contact : NSObject, NSCoding{
var image : UIImage?
var firstName : String?
var lastName : String?
var email : String?
var phoneNumber : String?
var address : String?
var bills : [Bill]?
init(image: UIImage, firstName : String, lastName : String, email : String, phoneNumber : String, address : String, bills : [Bill]) {
self.image = image
self.firstName = firstName
self.lastName = lastName
self.email = email
self.phoneNumber = phoneNumber
self.address = address
self.bills = bills
}
// MARK: NSCoding
required convenience init?(coder decoder: NSCoder) {
guard let image = decoder.decodeObjectForKey("image") as? UIImage,
let firstName = decoder.decodeObjectForKey("firstName") as? String,
let lastName = decoder.decodeObjectForKey("lastName") as? String,
let email = decoder.decodeObjectForKey("email") as? String,
let phoneNumber = decoder.decodeObjectForKey("phoneNumber") as? String,
let address = decoder.decodeObjectForKey("address") as? String,
let bills = decoder.decodeObjectForKey("bills") as? [Bill]
else {
return nil
}
self.init(
image: image,
firstName: firstName,
lastName : lastName,
email : email,
phoneNumber : phoneNumber,
address : address,
bills : bills
)
}
func encodeWithCoder(coder: NSCoder) {
coder.encodeObject(self.image, forKey: "image")
coder.encodeObject(self.firstName, forKey: "firstName")
coder.encodeObject(self.lastName, forKey: "lastName")
coder.encodeObject(self.email, forKey: "email")
coder.encodeObject(self.phoneNumber, forKey: "phoneNumber")
coder.encodeObject(self.address, forKey: "address")
coder.encodeObject(self.bills, forKey: "bills")
}
}
/* Bill.swift*/
import Foundation
class Bill : NSObject, NSCoding{
var service : String?
var subtotal : Double?
var taxes : Double?
var total : Double?
init(service : String, subtotal : Double, taxes : Double, total: Double) {
self.service = service
self.subtotal = subtotal
self.taxes = taxes
}
// MARK: NSCoding
required convenience init?(coder decoder: NSCoder) {
guard let service = decoder.decodeObjectForKey("service") as? String,
let subtotal = decoder.decodeObjectForKey("subtotal") as? Double,
let taxes = decoder.decodeObjectForKey("taxes") as? Double,
let total = decoder.decodeObjectForKey("total") as? Double
else {
return nil
}
self.init(
service: service,
subtotal: subtotal,
taxes: taxes,
total: total
)
}
func encodeWithCoder(coder: NSCoder) {
coder.encodeObject(self.service, forKey: "service")
coder.encodeObject(self.subtotal, forKey: "subtotal")
coder.encodeObject(self.taxes, forKey: "taxes")
coder.encodeObject(self.total, forKey: "total")
}
}
Here is a guide from the apple dev docs (in objective-c):
Discussion You must return self from initWithCoder:. If you have an
advanced need that requires substituting a different object after
decoding, you can do so in awakeAfterUsingCoder:
https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Archiving/Articles/codingobjects.html
- (void)encodeWithCoder:(NSCoder *)coder {
[super encodeWithCoder:coder];
// Implementation continues
}
- (id)initWithCoder:(NSCoder *)coder {
self = [super init];
if (self) {
_firstName = [coder decodeObjectForKey:ASCPersonFirstName];
_lastName = [coder decodeObjectForKey:ASCPersonLastName];
_height = [coder decodeFloatForKey:ASCPersonHeight];
}
return self;
}
A call to super.init() is required in the serializable class's init method.
Snippet from Bill.swift
required init?(coder decoder: NSCoder) {
super.init()
service = decoder.decodeObjectForKey("service") as? String
subtotal = decoder.decodeObjectForKey("subtotal") as? Double
taxes = decoder.decodeObjectForKey("taxes") as? Double
total = decoder.decodeObjectForKey("total") as? Double
services = decoder.decodeObjectForKey("services") as? [Service]
}

Resources