从 NSUserDefaults 检索自定义对象
Posted
技术标签:
【中文标题】从 NSUserDefaults 检索自定义对象【英文标题】:Retrieving custom Object from NSUserDefaults 【发布时间】:2019-09-17 22:42:45 【问题描述】:我有一本价值观字典
class Objects
let values = [
"AAA": ["AAAAAAA", "111111111"],
"BBB": ["BBBBBBBB", "2222222"],
"CCC": ["CCCCCCCC", "3333333333"],
"DDD": ["DDDDDD", "44444444"],
]
我将其转换为自定义对象并显示在表格视图中。
struct Object
var heading : String!
var imageName: String!
然后用户可以选择两个对象存储在UserDefaults
中
let defaults = UserDefaults.standard
func addObject(_ object1: String, object2: String)
// Get objects for user
var userObjects = fetchObjectsFromUserDefaults()
// Add to user currencies
userObjects.append([object1,object2])
//Update user defaults value for key
// [ [Object1, Object2], [Object1, Object2] ]
defaults.set(userObject, forKey: "userCurrencies")
// Gets [[String]] values from user defaults for key
func fetchObjectsFromUserDefaults() -> [[String]]
if let objects = UserDefaults.standard.value(forKey: "userObjects")
return objects as! [[String]]
else
return []
// Uses [[String]] values and turns them into objects by using the dictionary to determine property values
func getObject() -> [[Object]]
let userObject = fetchObjectsFromUserDefaults()
// [ [Object1, Object2], [Object1, Object2] ]
let object = Object()
var fetchedObject = [[Object]]()
if !userObjects.isEmpty
for c in userObjects
var set = [Object]()
if let val = object.available[c[0]]
set.append(Currency(currencyTitle: c[0], imageName: val[0] ))
if let val2 = object.available[c[1]]
set.append(Currency(currencyTitle: c[0], imageName: val2[0] ))
if !set.isEmpty
fetchedObjects.append(set)
return fetchedObjects
return [[]]
视图控制器
在这里我将对象加载到TableView
let fetched = dataManager.getObjects
print(fetched)
self.objects = fetched()
但是这会打印出来
(功能)
我做错了什么,他们是从用户默认值中存储和检索这些数据的更好方法吗?我觉得这已经结束了,还有一种更快捷、更安全的方法。
【问题讨论】:
您只调用该函数一次。看起来您至少可能想在print
语句中调用它(print(fetched())
以打印结果。或者打印语句甚至是您要解决的问题?
您需要使您的自定义对象符合 NSCoding 并且您需要对其进行编码/解码并将其作为数据保存到 UserDefaults。顺便说一句,不要使用 value(forKey:) 方法,它仅适用于 KVO,如果您使用的是 Swift 4 或更高版本,最好使用 Codable 协议来编码/解码您的自定义对象。
另外要提的是结构不能符合 NSCoding(你需要继承 NSObject)。使其符合 Codable 协议并将编码数据保存到 plist 文件中
【参考方案1】:
第 1 步。
制作你的结构Codable
。如果您的struct
的所有成员都是Codable
并且幸运的是String
是Codable
,那么编译器将为您编写所有函数,所以它只是:
struct Object: Codable
var heading : String!
var imageName: String!
第 2 步。
Codable
的问题在于它与Data
相互转换,但您想与Dictionary
相互转换。幸运的是 JSONSerialization 从 Data
转换为 Dictionary
所以创建一个新协议并给它一个带有协议扩展的默认实现:
protocol JSONRepresentable
init?(json: [String: Any])
func json() -> [String: Any]
extension JSONRepresentable where Self: Codable
init?(json: [String:Any])
guard let value = (try? JSONSerialization.data(withJSONObject: json, options: []))
.flatMap ( try? JSONDecoder().decode(Self.self, from: $0) ) else
return nil
self = value
func json() -> [String:Any]
return (try? JSONEncoder().encode(self))
.flatMap try? JSONSerialization.jsonObject(with: $0, options: []) as? [String: Any] ?? [:]
第 3 步。
使你的结构符合JSONRepresentable
struct Object: Codable, JSONRepresentable
var heading : String!
var imageName: String!
第 4 步。
将您的对象放入 Userdefaults 并再次取出:
let o = Object.init(heading: "s", imageName: "a").json()
UserDefaults.standard.set(o, forKey: "test")
print(Object.init(json: UserDefaults.standard.dictionary(forKey: "test") ?? [:]))
如果你想试试,这里是整个游乐场:
import UIKit
struct Object: Codable, JSONRepresentable
var heading : String!
var imageName: String!
protocol JSONRepresentable
init?(json: [String: Any])
func json() -> [String: Any]
extension JSONRepresentable where Self: Codable
init?(json: [String:Any])
guard let value = (try? JSONSerialization.data(withJSONObject: json, options: []))
.flatMap ( try? JSONDecoder().decode(Self.self, from: $0) ) else
return nil
self = value
func json() -> [String:Any]
return (try? JSONEncoder().encode(self))
.flatMap try? JSONSerialization.jsonObject(with: $0, options: []) as? [String: Any] ?? [:]
let o = Object.init(heading: "s", imageName: "a").json()
UserDefaults.standard.set(o, forKey: "test")
print(Object.init(json: UserDefaults.standard.dictionary(forKey: "test") ?? [:]))
【讨论】:
谢谢!这是很大的帮助,只是试图让它完全适用于我的项目,例如添加对象时,我在 print 语句中得到以下内容Optional(TestApp.Currency(heading: nil, imageName: nil))
我还需要添加一对对象,因此在保存和检索它们时,对象的格式是一个包含两个对象的数组中的数组(我比较每个表格视图单元格中的每个对象)[[对象,对象]]
只是弄清楚这些最后的部分并做一些进一步的阅读,但这更多是我想要的
Array以上是关于从 NSUserDefaults 检索自定义对象的主要内容,如果未能解决你的问题,请参考以下文章
NSUserDefaults 简介,使用 NSUserDefaults 存储自定义对象
为啥 `NSUserDefaults` 不允许存储自定义类的对象?
如何在 Swift 中归档和取消归档自定义对象?或者如何在 Swift 中将自定义对象保存到 NSUserDefaults?
将自定义对象存储到 NSMutableArray,然后将此 NSMutableArray 存储到 NSUserDefaults