将 DateComponents 数组设置为 UserDefaults 不起作用

Posted

技术标签:

【中文标题】将 DateComponents 数组设置为 UserDefaults 不起作用【英文标题】:Setting DateComponents array to UserDefaults not working 【发布时间】:2019-07-13 22:46:39 【问题描述】:

我正在制作一个单视图应用程序,用于管理一个人处理的所有任务。我有两个数组:一个存储所有任务名称,一个显示任务的完成时间。我将这两个都分配给 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]()
    



然后我测试以确保数组正常工作:

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

setDefaults()

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

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

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

它只在这一行被调用,而不是在设置字符串数组的那一行。除此之外,阵列是相同的。我该如何解决这个问题?

【问题讨论】:

您不能将DateComponents 存储在UserDefaults 中。它不是数组、字典、字符串、日期、数字或数据。这些是您可以存储的唯一类型。 我使用了一个 DateComponents 数组。这应该有效吗? 否,因为 DateComponents 不在列表中。 【参考方案1】:

您不能将 DateComponents 对象数组直接保存到 UserDefaults,但可以保存其数据。 DateComponents 符合 Codable 协议,因此您只需使用 JSONEncoder/JSONDecoder 对数组进行编码/解码并保存结果数据。顺便说一句,我建议将其写入 JSON 文本文件,而不是使用 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) 


这将打印:

"["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"

【讨论】:

有没有具体的方法来改变数组? @user11107712 你是什么意思?我正在向它附加一个新元素。如果您在谈论loadedDateComponents,只需将其声明为变量。 与 1UserDefaults 一样,您必须输入 defaults.set(array, forKey: "key")。 JSON有类似的东西吗? 如果您想将其写入磁盘,只需执行do try finishingDatesData.write(to: fileURL) catch print(error)

以上是关于将 DateComponents 数组设置为 UserDefaults 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

从 String 创建 DateComponents / NSDateComponents,反之亦然

从 String 创建 DateComponents / NSDateComponents,反之亦然

如何在 Swift 中将 NSDateComponents 转换为 DateComponents

关于如何继续 UNUserNotificationCenter 64 限制的问题

Swift DateComponents 包含错误的小时值

设置 Quartus II 的仿真时间大于 1us