在 UserDefaults 中设置对象数组
Posted
技术标签:
【中文标题】在 UserDefaults 中设置对象数组【英文标题】:Set array of objects in UserDefaults 【发布时间】:2019-02-18 11:27:43 【问题描述】:如何在UserDefaults
中设置和获取json对象数组?
当我尝试如下设置时,我的应用程序崩溃了:
import SwiftyJSON
var finalArray = [JSON]()
UserDefaults.standard.set(finalArray, forKey: "attemptedArray")
我的数据如下:
[
"marked" : 3,
"attempted" : true,
"correct" : 3,
"subject" : 1,
"status" : true,
"question" : 219,
"answer" : 32931,
"time" : 15,
"score" : 5,
"chapter" : 26
,
"marked" : 4,
"attempted" : true,
"correct" : 4,
"subject" : 1,
"status" : true,
"question" : 550,
"answer" : 34256,
"time" : 23,
"score" : 10,
"chapter" : 26
,
"marked" : 1,
"attempted" : true,
"correct" : 1,
"subject" : 1,
"status" : true,
"question" : 566,
"answer" : 34317,
"time" : 33,
"score" : 14,
"chapter" : 26
]
【问题讨论】:
"我的应用程序崩溃" 错误信息是什么?JSON
似乎不符合 NSCoding 标准,您无法将任何您想要的内容保存到 UserDefaults
中(您需要将其转换为允许的类型)。检查它的文档。
它无法保存用户创建的类的对象...您正在保存“JSON”的对象,将其转换为字典,然后您可以保存
您有名为finalArr
的变量,但您正在设置finalArray
。请使用正确的变量。
你可以转换成[[String : Any]]
?
这是在滥用用户默认设置。请不要滥用用户默认设置。
【参考方案1】:
UserDefaults
无法保存 SwiftyJSON 的 JSON
类型。你必须保存一些他们支持的类型,在这种情况下,你正在寻找Data
。
无论如何,将Data
保存到UserDefaults
并不是最好的,您应该将Data
保存到其他地方。为此,您可以使用FileManager
。
因此,为您的数据创建自定义模型,而不是使用 JSON
并将 Codable
应用于您的自定义模型
struct Model: Codable
var marked, correct, subject, question, answer, time, score, chapter: Int
var attempted, status: Bool
那么你应该使用 Model
作为数组中的元素类型(请注意,你需要使用 JSONDecoder
解码来自 Data
的响应(见下文))
var finalArray = [Model]()
然后您可以使用JSONEncoder
将您的模型数组编码为Data
,您可以将其写入某个文件
do
let encoded = try JSONEncoder().encode(finalArray)
let preferencesDirectoryURL = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask).first!.appendingPathComponent("Preferences", isDirectory: true)
let fileURL = preferencesDirectoryURL.appendingPathComponent("fileName.json")
try encoded.write(to: fileURL)
catch print(error)
和JSONDecoder
用于从保存的文件中解码Data
do
let preferencesDirectoryURL = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask).first!.appendingPathComponent("Preferences", isDirectory: true)
let fileURL = preferencesDirectoryURL.appendingPathComponent("fileName.json")
if let data = try? Data(contentsOf: fileURL)
let decoded = try JSONDecoder().decode([Model].self, from: data)
catch print(error)
【讨论】:
Codable 实现很好。它不是将数据保存到 UserDefaults。意思是只存储App的界面状态。它不适用于存储一般应用程序数据。您可以将数据写入磁盘到单独的文件.json
(这只是一个正确格式化的简单文本文件)到 UserDefaults 用来存储其首选项文件Library/Preferences
***.com/a/34701970/2303865的同一目录中。
相关developer.apple.com/library/archive/documentation/…【参考方案2】:
do
try let data = NSKeyedArchiver.archivedData(withRootObject: finalArray, requiringSecureCoding: false)
UserDefaults.standard.set(data, forKey: "attemptedArray")
catch
print("Print exception here")
阅读:-Property List Programming Guide
【讨论】:
以 NSException 类型的未捕获异常终止 @DeepakVerma,请参阅更新后的答案。您需要使用符合 ios 12 的最新语法【参考方案3】:由于某些原因,不建议在 NSuser 默认值中保存大量数据:
如果您要删除阵列的某些单元,您需要从 nsuser 默认值中删除它们。只有将它们保存为 数组而不是个体。
如果您选择在每次删除或添加一项时将它们保存为数组,则需要将它们全部保存。如果数组很大,可能需要一些时间
任何人都可以访问 NSuser 默认值。所以不安全
无论如何,我真的建议使用核心数据。它为您省去了我提到的所有麻烦。
【讨论】:
以上是关于在 UserDefaults 中设置对象数组的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI 在 UserDefaults 中设置字符串值,但作为`EnvironmentObject`