【问题标题】:How do I save NSUserDefaults when dictionary key has a Null value当字典键具有 Null 值时,如何保存 NSUserDefaults
【发布时间】:2016-07-01 22:16:38
【问题描述】:

我有一个使用SwiftForms 的项目。 有一个导航栏按钮,它执行将 textFields 中的信息发送到 NSUserDefaults 的功能。但是,如果我有一个空的 textField,应用程序会崩溃,但是当所有字段都被填写时,数据会被保存。我是否只是在函数中添加一个检查以查找NSNull

func submit(_: UIBarButtonItem!) {
    let message = self.form.formValues()
    //message is [String : AnyObject]
    let userDefaults = NSUserDefaults.standardUserDefaults()
    userDefaults.setObject(message as Dictionary, forKey: "theMessage")
    print("\n Message Saved! \n")
    print(message)
} 

这是我点击保存但未填写任何字段导致应用崩溃时出现的错误:

Attempt to set a non-property-list object {
    birthday = "<null>";
    job = "<null>";
    lastName = "<null>";
    name = "<null>";
    segmented = "<null>";
    stepper = 20;
    textview = "<null>";
} as an NSUserDefaults/CFPreferences value for key theMessage

这是我填写所有字段后得到的结果 - 没有崩溃

 --- Message Saved! --- 

["segmented": 1, "job": Job, "lastName": Last, "birthday": 2016-07-01 22:00:12 +0000, "textview": Etiam porta sem malesuada magna mollis euismod. Vestibulum id ligula porta felis euismod semperac, vestibulum at eros., "stepper": 22, "name": First]

【问题讨论】:

  • 将代码发布到您要在字典中添加值的位置。
  • 与 Swift 字典不同,NSDictionary 不能包含空值。你的formValues 函数应该返回一个没有选项的字典;要么将 "", NSNull 放在空值中,或者甚至更好,省略没有值的键。

标签: ios swift swift2 nsdictionary nsuserdefaults


【解决方案1】:

Swift 类现在是 UserDefaultsNSUserDefaults 是一个 Objective-C 类)。但是,它并没有改变 Swift 不能在该类中存储具有 nil 值的字典这一事实。因此,只需先将字典归档为Data

var someDictionary: [String: String?] = ["a": nil, "b": "beta"]

do {

    let data = try NSKeyedArchiver.archivedData(withRootObject: someDictionary, requiringSecureCoding: false)
    UserDefaults.standard.set(data, forKey: "someKey")

} catch let error {
    print(error)
}

要检索字典,只需将其解压缩:

if let def = UserDefaults.standard.object(forKey: "someKey") as? Data,
    let d = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(def) as? [String: String?] {
    print(d) // ["a": nil, "b": Optional("beta")]
}

在上面的示例中,try? 关键字将结果作为可选项处理。如果您希望处理错误,请使用 do-try-catch 模式:

if let def = UserDefaults.standard.object(forKey: "someKey") as? Data {

    do {

        if let d = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(def) as? [String: String?] {
            print(d) // ["a": nil, "b": Optional("beta")]
        }

    } catch {
        print(error)
    }

}

您可以将任何对象写入磁盘,只要它符合NSCoding 协议即可。

【讨论】:

    【解决方案2】:

    formValues 返回NSNull 用于无法保存在NSDictionary 中的空值,如Paulw11 所述。

    您可以使用此功能对其进行过滤。

    let filtered = message.filter({!$1.isKindOfClass(NSNull)}).reduce([:]) { ( dic , e) -> [String:AnyObject] in
                var dic = dic
                dic[e.0 as! String] = e.1
                return dic
            }
    

    然后将filtered保存在userDefaults

    【讨论】:

    • 哦,男孩,我必须通过该代码 sn-p 并剖析它以了解发生了什么。我感谢您的帮助。我开始添加for (key,value) in message { if value is NSNull { message[key] = "" as String }}
    • 这也是一种有效的方法,你试过sn-p吗,如果有效,请接受答案。
    • 答案已接受,您介意解释一下闭包,以便包括我自己在内的其他菜鸟能够更多地理解高阶函数和闭包吗?
    • @Ken,我发现这篇文章有带有 reduce 示例的过滤器,arsenkin.com/… 请告诉我您不清楚的任何具体内容:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-12
    • 2019-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-15
    相关资源
    最近更新 更多