尝试将元素添加到 NSUserDefaults 时出现 App Delegate 奇怪错误
App Delegate weird error when trying to add element to NSUserDefaults
我的 运行 我的应用程序在 Xcode 7 (Swift 2) 上出现了一个非常奇怪的错误,显示 "Thread 1: signal SIGABRT" 运行 错误我的应用程序的 App Delegate class 中的消息。然而,我实际上已经在 App Delegate class 中多次收到此 "Thread 1: signal SIGABRT" 运行 错误消息,主要是在我的代码中删除插座引用并忘记从情节提要中删除它时.但这肯定是我第一次在尝试发出命令时遇到同样的错误:
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")
发生的情况是,如果我只注释行 NSUserDefaults.standardUserDefaults().setObject(gains, forKey: "gains")
,应用程序不会崩溃!所以错误可能就在那一行。
如果有人能帮助我,我会非常感谢你。
PS:WastesGainsClass格式是这样的:
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
}
}
不幸的是,NSUserDefaults
不能接受任意对象,只能接受可以在 属性 列表中编码的对象。请参阅 Apple's reference guide for Property Lists 了解可以存储哪些对象。
如果您需要保存多个 WastesGainsClass
对象,您可能希望编写一个 returns 一个 Dictionary
编码其 属性 列表表示属性的方法,并且接受这样的初始化器 Dictionary
来恢复对象。
但是,如果您确实需要像这样保存多个自定义对象,您可能根本不想使用 NSUserDefaults
。考虑一个基于文档的应用程序,并查看 NSCoding
.
您 post 编写的代码试图将自定义对象数组保存到 NSUserDefaults。你不能那样做。实现 NSCoding 方法没有帮助。您只能在 NSUserDefaults 中存储 NSArray、NSDictionary、NSString、NSData、NSNumber 和 NSDate 等内容。
您需要将该对象转换为 NSData(就像您在某些代码中所做的那样)并将该 NSData 存储在 NSUserDefaults 中。如果需要,您甚至可以存储 NSData 的 NSArray。
看到这个 post : Attempt to set a non-property-list object as an NSUserDefaults
来自 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.
在Swift中你还可以使用:
Int
、UInt
、Double
、Float
和 Bool
类型,因为它们会自动桥接到 NSNumber
;
String
桥接到 NSString
[AnyObject]
因为桥接到 NSArray
;
[NSObject: AnyObject]
因为它桥接到 NSDictionary
。
当然数组元素和字典值的类型必须是以上类型之一。字典键类型必须是 NSString
(或桥接 String
)。
要存储任何其他 class 的实例,您有两个选择:
您的自定义 class 必须是 NSObject
的子class 并且符合
NSCoding
协议,然后您可以使用 NSKeyedArchiver.archivedDataWithRootObject()
将此 class 的对象存档到 NSData
并将其保存到 NSUserDefaults
并稍后从 NSUserDefaults
检索它并使用 NSKeyedUnarchiver.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([=10=]) }, forKey: "gains")
if let gainsData = NSUserDefaults.standardUserDefaults().objectForKey("gains") as? [NSData] {
gains = gainsData.map { NSKeyedUnarchiver.unarchiveObjectWithData([=10=]) as! WastesGainsClass }
}
您可以将自定义对象属性保存到字典中并存储它
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 { [=11=].toDict() }, forKey: "gains")
if let dicts = NSUserDefaults.standardUserDefaults().objectForKey("gains") as? [[NSObject: AnyObject]] {
gains = dicts.map { WastesGainsClass(dict: [=11=]) }
}
我的 运行 我的应用程序在 Xcode 7 (Swift 2) 上出现了一个非常奇怪的错误,显示 "Thread 1: signal SIGABRT" 运行 错误我的应用程序的 App Delegate class 中的消息。然而,我实际上已经在 App Delegate class 中多次收到此 "Thread 1: signal SIGABRT" 运行 错误消息,主要是在我的代码中删除插座引用并忘记从情节提要中删除它时.但这肯定是我第一次在尝试发出命令时遇到同样的错误:
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")
发生的情况是,如果我只注释行 NSUserDefaults.standardUserDefaults().setObject(gains, forKey: "gains")
,应用程序不会崩溃!所以错误可能就在那一行。
如果有人能帮助我,我会非常感谢你。
PS:WastesGainsClass格式是这样的:
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
}
}
NSUserDefaults
不能接受任意对象,只能接受可以在 属性 列表中编码的对象。请参阅 Apple's reference guide for Property Lists 了解可以存储哪些对象。
如果您需要保存多个 WastesGainsClass
对象,您可能希望编写一个 returns 一个 Dictionary
编码其 属性 列表表示属性的方法,并且接受这样的初始化器 Dictionary
来恢复对象。
但是,如果您确实需要像这样保存多个自定义对象,您可能根本不想使用 NSUserDefaults
。考虑一个基于文档的应用程序,并查看 NSCoding
.
您 post 编写的代码试图将自定义对象数组保存到 NSUserDefaults。你不能那样做。实现 NSCoding 方法没有帮助。您只能在 NSUserDefaults 中存储 NSArray、NSDictionary、NSString、NSData、NSNumber 和 NSDate 等内容。
您需要将该对象转换为 NSData(就像您在某些代码中所做的那样)并将该 NSData 存储在 NSUserDefaults 中。如果需要,您甚至可以存储 NSData 的 NSArray。
看到这个 post : Attempt to set a non-property-list object as an NSUserDefaults
来自 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.
在Swift中你还可以使用:
Int
、UInt
、Double
、Float
和Bool
类型,因为它们会自动桥接到NSNumber
;String
桥接到NSString
[AnyObject]
因为桥接到NSArray
;[NSObject: AnyObject]
因为它桥接到NSDictionary
。
当然数组元素和字典值的类型必须是以上类型之一。字典键类型必须是 NSString
(或桥接 String
)。
要存储任何其他 class 的实例,您有两个选择:
您的自定义 class 必须是
取消存档NSObject
的子class 并且符合NSCoding
协议,然后您可以使用NSKeyedArchiver.archivedDataWithRootObject()
将此 class 的对象存档到NSData
并将其保存到NSUserDefaults
并稍后从NSUserDefaults
检索它并使用NSKeyedUnarchiver.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([=10=]) }, forKey: "gains") if let gainsData = NSUserDefaults.standardUserDefaults().objectForKey("gains") as? [NSData] { gains = gainsData.map { NSKeyedUnarchiver.unarchiveObjectWithData([=10=]) as! WastesGainsClass } }
您可以将自定义对象属性保存到字典中并存储它
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 { [=11=].toDict() }, forKey: "gains") if let dicts = NSUserDefaults.standardUserDefaults().objectForKey("gains") as? [[NSObject: AnyObject]] { gains = dicts.map { WastesGainsClass(dict: [=11=]) } }