我正在尝试存储一组自定义结构。
在下面的尝试中,我在saveSampleArrayOfQuerySettings()的第二行中遇到运行时错误,抱怨转换为AnyObject。
struct QuerySettings {
// let ARRAY_INDEX_WHERE_TO_SAVE_STRUCT = 0
let QUERY_SETTINGS_KEY = "querysettings"
let defaults = NSUserDefaults.standardUserDefaults()
private var _includeCompletedReminders: Bool = false // Default value
var includeCompletedReminders: Bool {
get {
// If value has been set before then use it otherwise retrieve it.
return _includeCompletedReminders
} set (newVal) {
_includeCompletedReminders = newVal
// saveSettings(self, index: ARRAY_INDEX_WHERE_TO_SAVE_STRUCT, saveKey: QUERY_SETTINGS_KEY)
}
}
private var _includeRemindersWithNoDueDate: Bool = true
var includeRemindersWithNoDueDate: Bool {
get {
return _includeRemindersWithNoDueDate
} set (newVal) {
_includeRemindersWithNoDueDate = newVal
// saveSettings(self, index: ARRAY_INDEX_WHERE_TO_SAVE_STRUCT, saveKey: QUERY_SETTINGS_KEY)
}
}
}
func saveSampleArrayOfQuerySettings(saveKey: String) {
let sampleArray = [QuerySettings(), QuerySettings()]
// Persist
let archivedSettingsArray = NSKeyedArchiver.archivedDataWithRootObject(sampleArray as! AnyObject)
// RUNTIME ERROR AT PREVIOUS LINE: "Could not cast value of type 'Swift.Array<RemindersPro.QuerySettings>' (0x112df10d8) to 'Swift.AnyObject' (0x1169d6018)."
NSUserDefaults.standardUserDefaults().setObject(archivedSettingsArray, forKey: saveKey)
NSUserDefaults.standardUserDefaults().synchronize()
// For Testing Purposes - Load the saved settings
if let retrievedArchivedSettingsArray : AnyObject = NSUserDefaults.standardUserDefaults().objectForKey(saveKey) {
if let settingsArray : AnyObject = NSKeyedUnarchiver.unarchiveObjectWithData(retrievedArchivedSettingsArray as! NSData) {
let arr = settingsArray as! [QuerySettings]
print(arr.first)
}
}
}
saveSampleArrayOfQuerySettings("saveKey")
我想知道是否需要对结构进行编码。我查看了这些帖子,但奇怪的是甚至无法让帖子中的样本正常工作(更不用说将它们应用到我的代码中了。)
How to save an array of objects to NSUserDefault with swift?
(Swift) Storing and retrieving Array to NSUserDefaults
How to save an array of custom structs to plist swift
请告诉我如何使其正常工作?
答案 0 :(得分:4)
你的代码太冗长了:
true
或false
足以让编译器推导出您想要的Bool
。 Swift是围绕这样的想法而构建的,即编译器可以非常智能地减轻程序员的负担。现在,关于归档的主题:您将会惊愕地了解NSCoding
仅适用于从NSObject
继承的对象。结构不能与NSCoding
一致。你需要把它包装在一个帮助器类中。
以下是我提出的建议:
protocol ArchivableStruct {
var dataDictionary: [String: AnyObject] { get }
init(dataDictionary aDict: [String: AnyObject])
}
class StructArchiver<T: ArchivableStruct>: NSObject, NSCoding {
var structValue: T
init(structValue: T) {
self.structValue = structValue
}
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(self.structValue.dataDictionary, forKey: "dataDictionary")
}
required init?(coder aDecoder: NSCoder) {
let dataDictionary = aDecoder.decodeObjectForKey("dataDictionary") as! [String: AnyObject]
self.structValue = T(dataDictionary: dataDictionary)
}
}
字典是归档的。在回来的路上,我们只需解压缩这个Dictionary来获取结构。我们无需担心QUERY_SETTINGS_KEY
和defaults
,因为前者是常量,后者有自己的数据源(NSUserDefaults
)。
struct QuerySettings: ArchivableStruct {
let QUERY_SETTINGS_KEY = "querysettings"
let defaults = NSUserDefaults.standardUserDefaults()
var includeCompletedReminders = false
var includeRemindersWithNoDueDate = true
init(includeCompletedReminders: Bool, includeRemindersWithNoDueDate: Bool) {
self.includeCompletedReminders = includeCompletedReminders
self.includeRemindersWithNoDueDate = includeRemindersWithNoDueDate
}
// --------------------------------------
// ArchivableStruct protocol
// --------------------------------------
var dataDictionary: [String: AnyObject] {
get {
return [
"includeCompletedReminders": self.includeCompletedReminders,
"includeRemindersWithNoDueDate": self.includeRemindersWithNoDueDate
]
}
}
init(dataDictionary aDict: [String : AnyObject]) {
self.includeCompletedReminders = aDict["includeCompletedReminders"] as! Bool
self.includeRemindersWithNoDueDate = aDict["includeRemindersWithNoDueDate"] as! Bool
}
}
struct
映射到帮助程序类由于您没有归档QuerySetting
结构但是它们的数组,因此还有一个额外步骤可将其映射到StructArchiver<T>
,以便您的数组可以存档:
// Set up a sample array
let a = QuerySettings(includeCompletedReminders: true, includeRemindersWithNoDueDate: false)
let b = QuerySettings(includeCompletedReminders: false, includeRemindersWithNoDueDate: true)
let sampleArray = [a, b]
// Archive
let wrapperArray = sampleArray.map { StructArchiver(structValue: $0) }
let data = NSKeyedArchiver.archivedDataWithRootObject(wrapperArray)
// Unarchive
let unwrapperArray = NSKeyedUnarchiver.unarchiveObjectWithData(data) as! [StructArchiver<QuerySettings>]
let unarchivedArray = unwrapperArray.map { $0.structValue }