我正在尝试在 iOS UserDefaults 中存储映射到公司对象(来自结构公司)的公司名称(字符串)字典。我创建了 Company 结构并使其符合 Codable。我有一个例子,一位朋友在我的项目中帮助我创建了一个类 Account,并通过创建一个 Defaults 结构(将包括示例代码)将其存储在 UserDefaults 中。我在 swift 文档中读到字典符合 Codable 并且为了保持 Codable,必须包含 Codable 对象。这就是我让 struct Company 符合 Codable 的原因。
我为公司创建了一个符合 Codable 的结构。我尝试使用模型代码创建一个新的结构 CompanyDefaults 来处理公司字典从/到 UserDefaults 的获取和设置。我觉得我对需要发生的事情以及应该如何实施(考虑到良好的设计)有一些初学者误解。
我希望存储的字典看起来像[String:Company]
公司名称将是 String 和 Company 的 Company 对象
我在做一些研究时使用了符合 Codable,它似乎是完成类似任务的新方法。
公司结构
struct Company: Codable {
var name:String?
var initials:String? = nil
var logoURL:URL? = nil
var brandColor:String? = nil // Change to UIColor
enum CodingKeys:String, CodingKey {
case name = "name"
case initials = "initials"
case logoURL = "logoURL"
case brandColor = "brandColor"
}
init(name:String?, initials:String?, logoURL:URL?, brandColor:String?) {
self.name = name
self.initials = initials
self.logoURL = logoURL
self.brandColor = brandColor
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
name = try values.decode(String.self, forKey: .name)
initials = try values.decode(String.self, forKey: .initials)
logoURL = try values.decode(URL.self, forKey: .logoURL)
brandColor = try values.decode(String.self, forKey: .brandColor)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(name, forKey: .name)
try container.encode(initials, forKey: .initials)
try container.encode(logoURL, forKey: .logoURL)
try container.encode(brandColor, forKey: .brandColor)
}
}
默认结构来控制存储
struct CompanyDefaults {
static private let companiesKey = "companiesKey"
static var companies: [String:Company] = {
guard let data = UserDefaults.standard.data(forKey: companiesKey) else { return [:] }
let companies = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? [String : Company] ?? [:]
return companies!
}() {
didSet {
guard let data = try? NSKeyedArchiver.archivedData(withRootObject: companies, requiringSecureCoding: false) else {
return
}
UserDefaults.standard.set(data, forKey: companiesKey)
}
}
}
我应该能够在我的代码中引用存储的字典,例如CompanyDefaults.companies.count
作为参考,一位朋友帮助我对存储在用户默认值中的一组 Account 类执行了类似的任务。完美适用的代码如下。我尝试不同方式的原因是我有不同的数据结构(字典)并决定使用结构。
class Account: NSObject, NSCoding {
let service: String
var username: String
var password: String
func encode(with aCoder: NSCoder) {
aCoder.encode(service)
aCoder.encode(username)
aCoder.encode(password)
}
required init?(coder aDecoder: NSCoder) {
guard let service = aDecoder.decodeObject() as? String,
var username = aDecoder.decodeObject() as? String,
var password = aDecoder.decodeObject() as? String else {
return nil
}
self.service = service
self.username = username
self.password = password
}
init(service: String, username: String, password: String) {
self.service = service
self.username = username
self.password = password
}
}
struct Defaults {
static private let accountsKey = "accountsKey"
static var accounts: [Account] = {
guard let data = UserDefaults.standard.data(forKey: accountsKey) else { return [] }
let accounts = NSKeyedUnarchiver.unarchiveObject(with: data) as? [Account] ?? []
return accounts
}() {
didSet {
guard let data = try? NSKeyedArchiver.archivedData(withRootObject: accounts, requiringSecureCoding: false) else {
return
}
UserDefaults.standard.set(data, forKey: accountsKey)
}
}
}