swift - NSUserDefaultsController:“尝试将非属性列表对象...设置为键的 NSUserDefaults/CFPreferences 值...”
问题描述
我正在尝试NSUserDefaultsController
在我的 Swift macOS 应用程序中实现首选项窗口。
我需要保留的设置之一是一组预设,由以下类定义:
class Preset: NSObject {
var name = "abc"
var value = 123
override init() {
super.init()
}
}
因此,我需要保留一个类型为 的变量[Presets]
。我的首选项窗口中的视觉表示是一个NSTableView
,绑定到一个NSArrayController
。
我按照本教程设置绑定。运行应用程序并尝试添加新预设(通过单击+
按钮)时,出现以下错误:
[User Defaults] Attempt to set a non-property-list object (...) as an NSUserDefaults/CFPreferences value for key presets
[General] Attempt to insert non-property list object (...) for key presets
我已经尝试实现Codable
andNSCoding
协议,但错误仍然存在。
通过在 Stack Overflow 中搜索类似问题(例如this或this),似乎解决方案将涉及NSKeyedArchiver
and NSKeyedUnarchiver
。如果您手动触发加载和保存,这看起来很简单。不幸的是,我看不到如何将这些类与NSUserDefaultsController
.
解决方案
我通过子类化解决了这个问题,NSArrayController
如下所示(见 Hamish 对我的另一个问题的评论,这是使这个通用的拼图的最后一个缺失部分):
extension Encodable {
fileprivate func encode(to container: inout SingleValueEncodingContainer) throws {
try container.encode(self)
}
}
struct AnyEncodable: Encodable {
var value: Encodable
init(_ value: Encodable) {
self.value = value
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try value.encode(to: &container)
}
}
class NSEncodableArrayController: NSArrayController {
override func addObject(_ object: Any) {
let data = try! PropertyListEncoder().encode(AnyEncodable(object as! Encodable))
let any = try! PropertyListSerialization.propertyList(from: data, options: [], format: nil)
super.addObject(any)
}
}
推荐阅读
- couchdb - 从 CouchDB v2.2.0 获取 502 Bad Gateway,并且每次使用新的 PID 重新启动 beam.smp
- android - (#100) 尝试将视频发布到 Facebook 页面时出现“主题应该是页面帐户”错误
- java - rxjava中throttleLatest和throttleLast有什么区别?
- keyboard - 有没有定义键码和/或键符的标准?
- go - 如何下载fabric-sdk-go的所有依赖?
- sql - SQL命令需要一个名为“@SessionID”的参数,在参数映射中没有找到
- vue.js - 为什么不改变我输入的值?
- sql-server - 在 MS SQL 的 WHERE 子句中如何制作案例
- c++ - 对从 Eigen 获得的特征值和特征向量进行排序的有效方法
- amazon-web-services - AWS Cloudformation 创建没有容器定义的任务定义