Xcode 15.3更新后NSTableView拖拽失效:NSKeyedUnarchiver适配问题
解决Xcode 15.3中NSKeyedUnarchiver新API导致拖拽数据解析失败的问题
问题出在新API的类校验逻辑上:拖拽过来的数组数据里包含具体的子元素类,而你之前只指定了NSArray.self,没有包含元素的实际类型,导致解包失败。
正确解决方案
在unarchivedObject(ofClasses:from:)中同时声明数组类和数组内元素的所有可能类:
- 如果数组里是系统类(比如NSString、NSURL),把这些类也加入列表:
if let draggedArray = try? NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSArray.self, NSString.self], from: data) as? [String] { // 处理解析后的拖拽数据 }
- 如果数组里是自定义类,先确保自定义类遵循
NSCoding,再把它加入类列表:
if let draggedItems = try? NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSArray.self, CustomDraggableItem.self], from: data) as? [CustomDraggableItem] { // 处理自定义拖拽元素 }
为什么旧API能用?
废弃的unarchiveTopLevelObjectWithData(_:)没有强制类校验,会自动尝试解包所有符合NSCoding的对象;而新API要求显式声明所有可能出现的类,缺一个都会导致解包返回nil,进而让拖拽功能失效。
调试小技巧
如果不知道数组里的元素类型,先用旧API解析后打印类型:
if let rawObject = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) { print("顶层对象类型:\(type(of: rawObject))") if let array = rawObject as? [Any] { array.forEach { print("子元素类型:\(type(of: $0))") } } }
把打印出来的所有子元素类都加入ofClasses列表即可。
内容的提问来源于stack exchange,提问作者Jon Brown
相关产品推荐
相关产品推荐

