问题
I've got a really weird error while running my app on Xcode 7 (Swift 2) that shows a "Thread 1: signal SIGABRT" running error message in the App Delegate class of my app. However I've actually already got this "Thread 1: signal SIGABRT" running error message in the App Delegate class lots of times, mainly when deleting an outlet reference in my code and forgetting to also delete it from storyboard. But that's certainly the first time I've got this same error when trying to make the command:
let wasteGain = WastesGainsClass(value: enteredMoney, originOrCat: segControlArray[segControl.selectedSegmentIndex], specification: plusEspecTField.text!, date: dateArray, mode: "gain")
gains.append(wasteGain)
NSUserDefaults.standardUserDefaults().setObject(gains, forKey: "gains")
What happens is that if I just comment the line NSUserDefaults.standardUserDefaults().setObject(gains, forKey: "gains")
the app doesn't crash! So the error might just be in that line.
If anyone could help me, I`d thank you so much.
PS: WastesGainsClass format is like this:
class WastesGainsClass {
var value:Int = 0
var origin:String
var specification:String
var date:[String]
var mode:String
var rowMode:Int = 0
init(value:Int, originOrCat:String, specification:String, date:[String], mode:String) {
self.value = value
self.origin = originOrCat
self.specification = specification
self.date = date
self.mode = mode
}
}
回答1:
From documentation:
The NSUserDefaults class provides convenience methods for accessing common types such as floats, doubles, integers, Booleans, and URLs. A default object must be a property list, that is, an instance of (or for collections a combination of instances of): NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. If you want to store any other type of object, you should typically archive it to create an instance of NSData.
In Swift you can also use:
Int
,UInt
,Double
,Float
andBool
types because they are automatically bridged toNSNumber
;String
bridged toNSString
[AnyObject]
because it is bridged toNSArray
;[NSObject: AnyObject]
because it is bridged toNSDictionary
.
Of course type of array elements and dictionary values must be one of above types. Dictionary key type must be NSString
(or bridged String
).
To store instances of any other class you have two options:
Your custom class must be subclass of
NSObject
and conform toNSCoding
protocol and then you can archive object of this class toNSData
withNSKeyedArchiver.archivedDataWithRootObject()
and save it toNSUserDefaults
and later retrieve it fromNSUserDefaults
and unarchive withNSKeyedUnarchiver.unarchiveObjectWithData()
:import Foundation class WastesGainsClass: NSObject, NSCoding { var value: Int init(value: Int) { self.value = value } required init(coder aDecoder: NSCoder) { value = aDecoder.decodeObjectForKey("value") as! Int } func encodeWithCoder(aCoder: NSCoder) { aCoder.encodeObject(value, forKey: "value") } } var gains = [WastesGainsClass(value: 1), WastesGainsClass(value: 2)] NSUserDefaults.standardUserDefaults().setObject(gains.map { NSKeyedArchiver.archivedDataWithRootObject($0) }, forKey: "gains") if let gainsData = NSUserDefaults.standardUserDefaults().objectForKey("gains") as? [NSData] { gains = gainsData.map { NSKeyedUnarchiver.unarchiveObjectWithData($0) as! WastesGainsClass } }
You can save your custom object properties to dictionary and store that dictionary in
NSUserDefaults
:import Foundation class WastesGainsClass { var value: Int init(value: Int) { self.value = value } } extension WastesGainsClass { convenience init(dict: [NSObject: AnyObject]) { self.init(value: dict["value"] as? Int ?? 0) } func toDict() -> [NSObject: AnyObject] { var d = [NSObject: AnyObject]() d["value"] = value return d } } var gains = [WastesGainsClass(value: 1), WastesGainsClass(value: 2)] NSUserDefaults.standardUserDefaults().setObject(gains.map { $0.toDict() }, forKey: "gains") if let dicts = NSUserDefaults.standardUserDefaults().objectForKey("gains") as? [[NSObject: AnyObject]] { gains = dicts.map { WastesGainsClass(dict: $0) } }
回答2:
NSUserDefaults
unfortunately can't accept arbitrary objects, only objects that can be encoded in a Property List. See Apple's reference guide for Property Lists to learn which objects can be stored.
If you need to save several WastesGainsClass
objects, you may wish to write a method that returns a Dictionary
encoding their Property List-representable properties, and an initializer that accepts such a Dictionary
to restore the object.
However, if you truly need to save multiple custom objects like this, you probably don't want to use NSUserDefaults
at all. Consider a document-based app, and look into NSCoding
.
回答3:
The code you posted tries to save an array of custom objects to NSUserDefaults. You can't do that. Implementing the NSCoding methods doesn't help. You can only store things like NSArray, NSDictionary, NSString, NSData, NSNumber, and NSDate in NSUserDefaults.
You need to convert the object to NSData (like you have in some of the code) and store that NSData in NSUserDefaults. You can even store an NSArray of NSData if you need to.
see this post : Attempt to set a non-property-list object as an NSUserDefaults
来源:https://stackoverflow.com/questions/32798887/app-delegate-weird-error-when-trying-to-add-element-to-nsuserdefaults