ios - Swift 4:将一组自定义对象(带有嵌套的自定义对象)保存并检索到 UserDefaults
问题描述
我正在尝试将一组自定义对象保存到 UserDefaults。我相信此时我应该正确保存,但我继续收到“无法识别的选择器”错误。我认为这可能是因为我的自定义对象的两个部分是其他自定义对象的数组。我在这里做错了什么?
物体:
class SaleObject: NSObject, NSCoding {
//MARK: Properties
var ranges: [RangeObject]
var timberSaleName: String
var lbOperatorName: String
var lbOperatorID: String
var timberSaleID: Int
var ID: Int
var contracts: [ContractObject]
//MARK: Initialization
init(ranges: [RangeObject], timberSaleName: String, lbOperatorName: String, lbOperatorID: String, timberSaleID: Int, ID: Int ,contracts: [ContractObject]) {
//Initialize stored properties
self.ranges = ranges
self.timberSaleName = timberSaleName
self.lbOperatorName = lbOperatorName
self.lbOperatorID = lbOperatorID
self.timberSaleID = timberSaleID
self.ID = ID
self.contracts = contracts
}
required init?(coder aDecoder: NSCoder) {
self.ranges = (aDecoder.decodeObject(forKey: "ranges") as? [RangeObject])!
self.timberSaleName = (aDecoder.decodeObject(forKey: "timber_sale_name") as? String)!
self.lbOperatorName = (aDecoder.decodeObject(forKey: "lb_operator_name") as? String)!
self.lbOperatorID = (aDecoder.decodeObject(forKey: "lb_operator_id") as? String)!
self.timberSaleID = (aDecoder.decodeObject(forKey: "timber_sale_id") as? Int)!
self.ID = (aDecoder.decodeObject(forKey: "id") as? Int)!
self.contracts = (aDecoder.decodeObject(forKey: "contracts") as? [ContractObject])!
}
func encode(with aCoder: NSCoder) {
aCoder.encode(self.ranges, forKey: "ranges")
aCoder.encode(self.timberSaleName, forKey: "timber_sale_name")
aCoder.encode(self.lbOperatorName, forKey: "lb_operator_name")
aCoder.encode(self.lbOperatorID, forKey: "lb_operator_id")
aCoder.encode(self.timberSaleID, forKey: "timber_sale_id")
aCoder.encode(self.ID, forKey: "id")
aCoder.encode(self.contracts, forKey: "contracts")
}
}
保存尝试:
let userDefaults = UserDefaults.standard
let encodedData: Data = NSKeyedArchiver.archivedData(withRootObject: self.saleArray)
userDefaults.set(encodedData, forKey: "sales")
错误:
2018-11-28 14:28:30.024768-0600 Load BOSS[14991:282335]
libMobileGestalt MobileGestalt.c:890: MGIsDeviceOneOfType is not
supported on this platform.
2018-11-28 14:28:30.362954-0600 Load BOSS[14991:282335] [MC] System
group container for systemgroup.com.apple.configurationprofiles path
is /Users/beauburchfield/Library/Developer/
CoreSimulator/Devices/4ED03814-DD8C-43F3-ABA7-
B5D0751161A0/data/Containers/Shared/SystemGroup/
systemgroup.com.apple.configurationprofiles
2018-11-28 14:28:30.364591-0600 Load BOSS[14991:282335] [MC] Reading
from private effective user settings.
2018-11-28 14:28:31.034136-0600 Load BOSS[14991:282394] -
[Load_BOSS.RangeObject encodeWithCoder:]: unrecognized selector sent
to
instance 0x600001bcc680
2018-11-28 14:28:31.037429-0600 Load BOSS[14991:282394] ***
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[Load_BOSS.RangeObject
encodeWithCoder:]: unrecognized selector sent to instance
0x600001bcc680'
*** First throw call stack:
(
0 CoreFoundation 0x000000010cbc51bb _ .
_exceptionPreprocess + 331
1 libobjc.A.dylib 0x000000010b73b735
objc_exception_throw + 48
2 CoreFoundation 0x000000010cbe3f44 -
[NSObject(NSObject) doesNotRecognizeSelector:] + 132
3 CoreFoundation 0x000000010cbc9ed6 ___forwarding___ + 1446
4 CoreFoundation 0x000000010cbcbda8 _CF_forwarding_prep_0 + 120
5 Foundation 0x000000010b182175 _encodeObject + 1230
6 Foundation 0x000000010b182aee -[NSKeyedArchiver _encodeArrayOfObjects:forKey:] + 439
7 Foundation 0x000000010b182175 _encodeObject + 1230
8 Load BOSS 0x000000010add0e2f $S9Load_BOSS10SaleObjectC6encode4withySo7NSCoderC_tF + 207
9 Load BOSS 0x000000010add128c $S9Load_BOSS10SaleObjectC6encode4withySo7NSCoderC_tFTo + 60
10 Foundation 0x000000010b182175 _encodeObject + 1230
11 Foundation 0x000000010b182aee -[NSKeyedArchiver _encodeArrayOfObjects:forKey:] + 439
12 Foundation 0x000000010b182175 _encodeObject + 1230
13 Foundation 0x000000010b18122e +[NSKeyedArchiver archivedDataWithRootObject:] + 156
14 Load BOSS 0x000000010adbf15a $S9Load_BOSS18MainViewControllerC14getJsonFromUrlyyFy10Foundation4DataVSg_So13NSURLResponseCSgs5Error_pSgtcfU_ + 15706
15 Load BOSS 0x000000010adbf43d $S9Load_BOSS18MainViewControllerC14getJsonFromUrlyyFy10Foundation4DataVSg_So13NSURLResponseCSgs5Error_pSgtcfU_TA + 13
16 Load BOSS 0x000000010adbf590 $S10Foundation4DataVSgSo13NSURLResponseCSgs5Error_pSgIegggg_So6NSDataCSgAGSo7NSErrorCSgIeyByyy_TR + 336
17 CFNetwork 0x000000010e0d9940 __75-[__NSURLSessionLocal taskForClass:request:uploadFile:bodyData:completion:]_block_invoke + 19
18 CFNetwork 0x000000010e0efb0c __49-[__NSCFLocalSessionTask _task_onqueue_didFinish]_block_invoke + 172
19 Foundation 0x000000010b1a8f9e __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 7
20 Foundation 0x000000010b1a8ea5 -[NSBlockOperation main] + 68
21 Foundation 0x000000010b1a5c14 -[__NSOperationInternal _start:] + 689
22 Foundation 0x000000010b1abc4b __NSOQSchedule_f + 227
23 libdispatch.dylib 0x000000010f0ae595 _dispatch_call_block_and_release + 12
24 libdispatch.dylib 0x000000010f0af602 _dispatch_client_callout + 8
25 libdispatch.dylib 0x000000010f0b254d _dispatch_continuation_pop + 565
26 libdispatch.dylib 0x000000010f0b1927 _dispatch_async_redirect_invoke + 859
27 libdispatch.dylib 0x000000010f0c000a _dispatch_root_queue_drain + 351
28 libdispatch.dylib 0x000000010f0c09af _dispatch_worker_thread2 + 130
29 libsystem_pthread.dylib 0x000000010f49e70e _pthread_wqthread + 619
30 libsystem_pthread.dylib 0x000000010f49e435 start_wqthread + 13
)
libc++abi.dylib: terminating with uncaught exception of type NSException
解决方案
这里的崩溃
[Load_BOSS.RangeObject encodeWithCoder:]:发送了无法识别的选择器
给出了使根类符合的原因
class SaleObject: NSObject, NSCoding {
并不意味着您可以使用自定义对象(RangeObject
在您的情况下)而不使其也符合
class RangeObject : NSObject, NSCoding {
强烈推荐使用Codable
class SaleObject: Codable {
let ranges: [RangeObject]
let timberSaleName: String
let lbOperatorName: String
let lbOperatorID: String
let timberSaleID: Int
let ID: Int
let contracts: [ContractObject]
}
class RangeObject : Codable {
// add it's properties
}
如何使用:
let data = try? JSONEncoder().encode(obj) // obj may be single SaleObject or array
let obj = try? JSONDecoder().decode(SaleObject.self,from:data) // for data being array make it [SaleObject].self
推荐阅读
- python - 如何让 python 程序(应该从 csv finl 中寻找变量)通过 PHP 运行并返回相应的变量?
- excel - 将数据表写入 Excel 文件
- powershell - PowerShell icacls - 如何赋予管理员完全权限,并从非管理员用户手中夺走所有权限?
- python - Python:TypeError:需要一个整数(获取类型 sqlite3.Cursor)
- javascript - 我们可以使用 GitLab 作为 AWS CDK 管道的源代码主机吗?
- mongodb - 有没有办法只在 mongoDB 中获取最新版本的文档
- python - 将日期与时间分开
- sql - 如何根据前一行中十进制值的比较来唯一标识 TSQL 中的特定行?
- machine-learning - sklearn 管道有没有办法在网格搜索期间进行有步骤和无步骤的训练?我可以删除步骤,但如何将其传递给 GridSearchCV?
- pytest - 我们如何验证 DAG 对象中是否没有循环