ios 尝试在 Swift 3 中保存自定义对象时尝试插入非属性列表对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/41355427/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Attempt to insert non-property list object when trying to save a custom object in Swift 3
提问by Isuru
I have a simple object which conforms to the NSCoding
protocol.
我有一个符合NSCoding
协议的简单对象。
import Foundation
class JobCategory: NSObject, NSCoding {
var id: Int
var name: String
var URLString: String
init(id: Int, name: String, URLString: String) {
self.id = id
self.name = name
self.URLString = URLString
}
// MARK: - NSCoding
required init(coder aDecoder: NSCoder) {
id = aDecoder.decodeObject(forKey: "id") as? Int ?? aDecoder.decodeInteger(forKey: "id")
name = aDecoder.decodeObject(forKey: "name") as! String
URLString = aDecoder.decodeObject(forKey: "URLString") as! String
}
func encode(with aCoder: NSCoder) {
aCoder.encode(id, forKey: "id")
aCoder.encode(name, forKey: "name")
aCoder.encode(URLString, forKey: "URLString")
}
}
I'm trying to save an instance of it in UserDefaults
but it keeps failing with the following error.
我正在尝试保存它的一个实例,UserDefaults
但它一直失败并出现以下错误。
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to insert non-property list object for key jobCategory'
由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“尝试为关键 jobCategory 插入非属性列表对象”
This is the code where I'm saving in UserDefaults
.
这是我保存的代码UserDefaults
。
enum UserDefaultsKeys: String {
case jobCategory
}
class ViewController: UIViewController {
@IBAction func didTapSaveButton(_ sender: UIButton) {
let category = JobCategory(id: 1, name: "Test Category", URLString: "http://www.example-job.com")
let userDefaults = UserDefaults.standard
userDefaults.set(category, forKey: UserDefaultsKeys.jobCategory.rawValue)
userDefaults.synchronize()
}
}
I replaced the enum value to key with a normal string but the same error still occurs. Any idea what's causing this?
我将枚举值替换为普通字符串,但仍然出现相同的错误。知道是什么原因造成的吗?
回答by Nirav D
You need to create Data
instance from your JobCategory
instance using NSKeyedArchiver.archivedData(withRootObject:)
and store that Data
instance in UserDefaults
and later unarchive using NSKeyedUnarchiver.unarchiveObject(with:)
, So try like this.
您需要使用Data
从您的JobCategory
实例创建实例NSKeyedArchiver.archivedData(withRootObject:)
并将该Data
实例存储在中UserDefaults
,然后使用 取消归档NSKeyedUnarchiver.unarchiveObject(with:)
,所以尝试这样。
For Storing data in UserDefaults
用于将数据存储在 UserDefaults
let category = JobCategory(id: 1, name: "Test Category", URLString: "http://www.example-job.com")
let encodedData = NSKeyedArchiver.archivedData(withRootObject: category)
let userDefaults = UserDefaults.standard
userDefaults.set(encodedData, forKey: UserDefaultsKeys.jobCategory.rawValue)
For retrieving data from UserDefaults
用于检索数据 UserDefaults
let decoded = UserDefaults.standard.object(forKey: UserDefaultsKeys.jobCategory.rawValue) as! Data
let decodedTeams = NSKeyedUnarchiver.unarchiveObject(with: decoded) as! JobCategory
print(decodedTeams.name)
回答by Harjot Singh
Update Swift 4, Xcode 10
更新 Swift 4、Xcode 10
I have written a struct around it for easy access.
我已经围绕它编写了一个结构,以便于访问。
//set, get & remove User own profile in cache
struct UserProfileCache {
static let key = "userProfileCache"
static func save(_ value: Profile!) {
UserDefaults.standard.set(try? PropertyListEncoder().encode(value), forKey: key)
}
static func get() -> Profile! {
var userData: Profile!
if let data = UserDefaults.standard.value(forKey: key) as? Data {
userData = try? PropertyListDecoder().decode(Profile.self, from: data)
return userData!
} else {
return userData
}
}
static func remove() {
UserDefaults.standard.removeObject(forKey: key)
}
}
Profile is a Json encoded object.
Profile 是一个 Json 编码的对象。
struct Profile: Codable {
let id: Int!
let firstName: String
let dob: String!
}
Usage:
用法:
//save details in user defaults...
UserProfileCache.save(profileDetails)
Hope that helps!!!
希望有帮助!!!
Thanks
谢谢
回答by Niraj Paul
Save dictionary Into userdefault
将字典保存到用户默认
let data = NSKeyedArchiver.archivedData(withRootObject: DictionaryData)
UserDefaults.standard.set(data, forKey: kUserData)
Retrieving the dictionary
检索字典
let outData = UserDefaults.standard.data(forKey: kUserData)
let dict = NSKeyedUnarchiver.unarchiveObject(with: outData!) as! NSDictionary
回答by Tomas Cordoba
Based on Harjot Singhanswer. I've used like this:
基于Harjot Singh 的回答。我是这样用的:
struct AppData {
static var myObject: MyObject? {
get {
if UserDefaults.standard.object(forKey: "UserLocationKey") != nil {
if let data = UserDefaults.standard.value(forKey: "UserLocationKey") as? Data {
let myObject = try? PropertyListDecoder().decode(MyObject.self, from: data)
return myObject!
}
}
return nil
}
set {
UserDefaults.standard.set(try? PropertyListEncoder().encode(newValue), forKey: "UserLocationKey")
}
}
}
回答by dimo hamdy
Swiftsave Codable
object to UserDefault
with @propertyWrapper
Swift将Codable
对象保存到UserDefault
with@propertyWrapper
@propertyWrapper
struct UserDefault<T: Codable> {
let key: String
let defaultValue: T
init(_ key: String, defaultValue: T) {
self.key = key
self.defaultValue = defaultValue
}
var wrappedValue: T {
get {
if let data = UserDefaults.standard.object(forKey: key) as? Data,
let user = try? JSONDecoder().decode(T.self, from: data) {
return user
}
return defaultValue
}
set {
if let encoded = try? JSONEncoder().encode(newValue) {
UserDefaults.standard.set(encoded, forKey: key)
}
}
}
}
enum GlobalSettings {
@UserDefault("user", defaultValue: User(name:"",pass:"")) static var user: User
}
Example User model confirm Codable
示例用户模型确认可编码
struct User:Codable {
let name:String
let pass:String
}
How to use it
如何使用它
//Set value
GlobalSettings.user = User(name: "Ahmed", pass: "Ahmed")
//GetValue
print(GlobalSettings.user)