简化NSPasteboard属性列表键值对的自定义键实现问题
解决NSPasteboard自定义字典键的运行时错误问题
问题根源
NSPasteboard的属性列表要求字典键必须是属性列表允许的类型(如NSString),而Swift自定义类型(即使遵循Hashable/RawRepresentable)作为字典键时,桥接到Objective-C会被包装成__SwiftValue对象,不符合属性列表格式要求,因此触发运行时错误。
可行解决方案
方案1:自定义结构体封装,保持简洁写法
通过结构体封装底层的[String: Any]字典,重载下标使用自定义键,同时提供转换为合规字典的接口:
// 定义自定义键枚举 enum CustomKey: String { case value case text } // 封装粘贴板数据的结构体 struct PasteboardData { private var storage: [String: Any] = [:] // 重载下标,使用自定义键读写 subscript(key: CustomKey) -> Any? { get { storage[key.rawValue] } set { storage[key.rawValue] = newValue } } // 输出符合要求的属性列表字典 var propertyList: [String: Any] { storage } }
使用示例:
var source = PasteboardData() source[.value] = 1 source[.text] = "Text" // 传入合规的字典给NSPasteboardItem let pbd = NSPasteboardItem(pasteboardPropertyList: source.propertyList, ofType: .experimental)
方案2:扩展NSPasteboardItem添加便捷初始化
直接扩展系统类,新增接受自定义键字典的初始化方法,内部自动转换为字符串键字典:
enum CustomKey: String { case value case text } extension NSPasteboardItem { convenience init(customPropertyList: [CustomKey: Any], ofType type: NSPasteboard.PasteboardType) { // 将自定义键字典转换为字符串键字典 let convertedDict = customPropertyList.reduce(into: [String: Any]()) { result, pair in result[pair.key.rawValue] = pair.value } self.init(pasteboardPropertyList: convertedDict, ofType: type) } }
使用示例:
let source: [CustomKey: Any] = [.value: 1, .text: "Text"] let pbd = NSPasteboardItem(customPropertyList: source, ofType: .experimental)
注意事项
- 确保字典中的值也是属性列表允许的类型(如
NSString、NSNumber、NSArray等),Swift基础类型会自动桥接,无需手动转换。 - 两种方案都保留了
.value、.text的简洁写法,同时规避了自定义键类型的桥接问题。
内容的提问来源于stack exchange,提问作者Ruben Kazumov
相关产品推荐
相关产品推荐

