【发布时间】:2019-06-26 04:49:09
【问题描述】:
我正在尝试在 iOS UserDefaults 中存储映射到公司对象(来自结构公司)的公司名称(字符串)字典。我创建了 Company 结构并使其符合 Codable。我有一个例子,一位朋友在我的项目中帮助我创建了一个类 Account,并通过创建一个 Defaults 结构(将包括示例代码)将其存储在 UserDefaults 中。我在 swift 文档中读到字典符合 Codable 并且为了保持 Codable,必须包含 Codable 对象。这就是我让 struct Company 符合 Codable 的原因。
我为 Company 创建了一个符合 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)
}
}
}
【问题讨论】:
标签: nsuserdefaults codable swift5 swift-dictionary nsarchiving