将DateComponents数组设置为UserDefaults不起作用 [英] Setting DateComponents array to UserDefaults not working

查看:87
本文介绍了将DateComponents数组设置为UserDefaults不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作一个单视图应用程序,该应用程序管理一个人可以完成的所有任务.我有两个数组:一个存储所有任务名称,另一个显示任务的完成时间.我将它们都分配给UserDefaults:

I'm making a single-view application which manages all the tasks one works on. I have two arrays: one that stores all the task names and on that shows the finishing times for the tasks. I assign both of those to UserDefaults:

var tasks = [String]()
var finishingDates = [DateComponents]()
let defaults = UserDefaults()
class ViewController: UIViewController {

    func setDefaults() {
        defaults.set(tasks, forKey: "tasks")
        defaults.set(finishingDates, forKey: "finishingDates")

    }
    override func viewDidLoad() {
        super.viewDidLoad()

        tasks = defaults.stringArray(forKey: "tasks") ?? [String]()
        finishingDates = defaults.array(forKey: "finishingDates") as? [DateComponents] ?? [DateComponents]()
    }


}

然后我进行测试以确保阵列可以正常工作:

Then I test to make sure the arrays are working:

tasks = ["task"]
finishingDates = [DateComponents(calendar: calendar, year: 1910, month: 10, day: 1)]

setDefaults()

但是,当我运行它时,该应用程序崩溃了.在应用程序委托中,存在SIGABRT错误.

However, when I run it, the app crashes. In the app delegate, there is the SIGABRT error.

我添加了一个异常断点,它在这一行被调用:

I add an exception breakpoint and it gets called on this line:

defaults.set(finishingDates, forKey: "finishingDates")

它仅在此行被调用,而不在设置String数组的行上被调用.除此之外,数组是相同的.我该如何解决?

It only gets called on this line and not on the line that sets the String array. Other than that, the arrays are identical. How can I solve this?

推荐答案

您不能将DateComponents对象的数组直接保存到UserDefaults,但是可以保存其Data. DateComponents符合Codable协议,因此您只需要使用JSONEncoder/JSONDecoder对数组进行编码/解码并保存结果数据.顺便说一句,我建议将其写入JSON文本文件,而不要使用UserDefaults持久保存:

You can't save an array of DateComponents objects directly to UserDefaults but you can save its Data. DateComponents conforms to Codable protocol so you just need to encode/decode your array using JSONEncoder/JSONDecoder and save the resulting data. Btw I recommend writing it to a JSON text file instead of persisting it with UserDefaults:

游乐场测试:

var finishingDates: [DateComponents] = []
finishingDates.append(.init(calendar: .current, year: 2019, month: 7, day: 13))
finishingDates.first!.month!
do {
    let finishingDatesData = try JSONEncoder().encode(finishingDates)
    print(String(data: finishingDatesData, encoding: .utf8) ?? "")

    UserDefaults.standard.set(finishingDatesData, forKey: "finishingDates")
    print("finishingDates saved to userdefaults")

    if let data = UserDefaults.standard.data(forKey: "finishingDates") {
        let loadedDateComponents = try JSONDecoder().decode([DateComponents].self, from: data)
        print(loadedDateComponents)  // "[calendar: gregorian (fixed) year: 2019 month: 7 day: 13 isLeapMonth: false ]\n"
    }
} catch { 
     print(error) 
}


这将打印:


This will print:

"[{" day:13," year:2019," calendar:{" locale:{" identifier:" en_US}," timeZone:{" identifier:" America \/Sao_Paulo}," identifier:" gregorian," minimumDaysInFirstWeek:1," firstWeekday:1}," month:7}] \ n"

"[{"day":13,"year":2019,"calendar":{"locale":{"identifier":"en_US"},"timeZone":{"identifier":"America\/Sao_Paulo"},"identifier":"gregorian","minimumDaysInFirstWeek":1,"firstWeekday":1},"month":7}]\n"

"[日历:公历(固定)年:2019个月:7天:13 isLeapMonth:false] \ n"

"[calendar: gregorian (fixed) year: 2019 month: 7 day: 13 isLeapMonth: false ]\n"

这篇关于将DateComponents数组设置为UserDefaults不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆