I'm creating a quick app that tracks user purchases in Swift. There's a Purchase class, and I'm trying to save an NSMutableArray of these to the user defaults.
When I go to load the data, after first pressing quitting the app to trigger a save, the else is always ran. Retrieving the integer amount (the data for KEY_WEEKLY_AMOUNT) is always successful though.
class UserDatas {
static let sharedInstance = UserDatas()
let defaults = NSUserDefaults.standardUserDefaults()
let KEY_ARRAY_OF_PURCHASES = "KEY_ARRAY_OF_PURCHASES"
let KEY_WEEKLY_AMOUNT = "KEY_WEEKLY_AMOUNT"
var arrayOfUserPurchases:NSMutableArray = NSMutableArray()
var weeklyAmount:Int = 0
func saveTheDatas() {
let arrayOfArchivedDatas = NSKeyedArchiver.archivedDataWithRootObject(arrayOfUserPurchases)
defaults.setObject(arrayOfArchivedDatas, forKey: KEY_ARRAY_OF_PURCHASES)
defaults.setInteger(weeklyAmount, forKey: KEY_WEEKLY_AMOUNT)
print("Saved data.")
}
func loadTheDatas() {
if let decodedNSDataBlob = defaults.objectForKey(KEY_ARRAY_OF_PURCHASES) as? NSData {
if let unarchivedArray = NSKeyedUnarchiver.unarchiveObjectWithData(decodedNSDataBlob) as? NSArray {
self.arrayOfUserPurchases = NSMutableArray.init(array: unarchivedArray)
}
} else {
// THIS ALWAYS HAPPENS. //
print("No Purchases yet! Initializing with blank array.")
arrayOfUserPurchases = NSMutableArray()
return
}
let savedWeeklyAmount = defaults.integerForKey(KEY_WEEKLY_AMOUNT)
self.weeklyAmount = savedWeeklyAmount
print("Loaded saved weekly amount: \(savedWeeklyAmount).")
}
And the Purchase class:
class Purchase : NSObject, NSCoding {
let KEY_PURCHASE_AMOUNT = "PURCHASE_AMOUNT"
let KEY_PURCHASE_CATEGORY = "PURCHASE_CATEGORY"
let KEY_PURCHASE_TIME = "PURCHASE_TIME"
let KEY_PURCHASE_DATE = "PURCHASE_DATE"
var amount:Int = 0
var time:String = ""
var date:String = ""
var category:Int = 0
var valid:Bool = false
init(amount:Int, time:String, date:String, category:Int) {
self.amount = amount
self.time = time
self.date = date
self.category = category
self.valid = true
}
override init() {
self.valid = false
}
// MARK: NSCoding
required convenience init?(coder aDecoder: NSCoder) {
guard let amount = aDecoder.decodeObjectForKey("amount") as? Int
else {
self.init()
return
}
guard let time = aDecoder.decodeObjectForKey("time") as? String
else {
self.init()
return
}
guard let date = aDecoder.decodeObjectForKey("date") as? String
else {
self.init()
return
}
guard let category = aDecoder.decodeObjectForKey("category") as? Int
else {
self.init()
return
}
guard let valid = aDecoder.decodeObjectForKey("valid") as? Bool
else {
self.init()
return
}
self.init(amount: amount, time: time, date: date, category: category)
}
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeInt(Int32(self.amount), forKey: "amount")
aCoder.encodeObject(self.time, forKey: "time")
aCoder.encodeObject(self.date, forKey: "date")
aCoder.encodeInt(Int32(self.category), forKey: "category")
aCoder.encodeBool(self.valid, forKey: "valid")
}
}
Your Purchase class needs following improvements
Instead of using a guard
statement use if let
like
if let amount = aDecoder.decodeObjectForKey("amount") as? Int
{
self.amount = amount
}
Forget about your init
calls inside initWithCoder, It is already initializing your object, so you don't need to init again
Also try to save your data using encodeObject
like
aCoder.encodeObject(amount, forKey: "amount")
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.