SwiftUI拖拽实现报错及自定义方案崩溃问题求助
SwiftUI拖拽功能问题修复
问题1:loadObject类型不匹配错误
报错信息:
Instance method 'loadObject(ofClass:completionHandler:)' requires that 'NSItemProvider' conform to '_ObjectiveCBridgeable'
问题原因
loadObject(ofClass:)参数传值错误——不应传入NSItemProvider.self,该方法需要指定你实际要加载的数据类型(比如String.self或URL.self)。另外,代码中试图将同一个item同时转为Tools和URL的逻辑不成立,单个item仅对应一种数据类型,需分别加载onDrag中注册的两类数据。
修正后的onDrop代码
.onDrop(of: ["public.text", "public.url"], isTargeted: nil) { providers, location in guard let provider = providers.first else { return false } // 加载工具类型(String格式) provider.loadObject(ofClass: String.self) { stringItem, error in guard let toolStr = stringItem as? String, let curTool = Tools(rawValue: toolStr) else { return } // 加载URL provider.loadObject(ofClass: URL.self) { urlItem, error in guard let dropURL = urlItem as? URL else { return } handleDrop(with: (curTool, dropURL)) } } return true } func handleDrop(with dropData: (Tools, URL)) { let (curTool, curURL) = dropData // 处理拖拽数据 }
问题2:自定义DragInfo后的Core Foundation崩溃
报错信息:
There are 0 items on the pasteboard, but 1 drag images. There must be 1 draggingItem per pasteboardItem.
问题原因
try? JSONEncoder().encode(draggedData)可能返回nil(比如枚举Tools未正确实现Codable协议),导致NSItemProvider无有效数据;- 自定义的
typeIdentifier需为合法的UTI(统一类型标识符),不能随意使用"xxx"这类无效值; - 直接传递
Data作为NSSecureCoding参数时,需确保数据编码成功且UTI匹配。
修正方案
步骤1:确保Tools枚举正确实现Codable
enum Tools: String, Codable { case circle, furniture // 其他枚举值 }
步骤2:修正onDrag代码,保证数据编码成功并使用合法UTI
struct DragInfo: Codable { let tool: Tools let url: URL } .onDrag { let draggedData = DragInfo(tool: .furniture, url: URL(string: "file://abc.txt") ?? URL(fileURLWithPath: "")) guard let data = try? JSONEncoder().encode(draggedData) else { // 编码失败时返回默认ItemProvider,避免崩溃 return NSItemProvider(object: "") } // 使用反向域名格式的自定义UTI,比如"com.yourdomain.draginfo" let uti = "com.yourdomain.draginfo" let itemProvider = NSItemProvider(item: data as NSSecureCoding?, typeIdentifier: uti) // 可选:注册额外类型以兼容其他场景 itemProvider.registerObject(draggedData.url as NSItemProviderWriting, visibility: .all) return itemProvider }
步骤3:对应的onDrop处理自定义UTI
.onDrop(of: ["com.yourdomain.draginfo"], isTargeted: nil) { providers, location in guard let provider = providers.first else { return false } provider.loadObject(ofClass: Data.self) { dataItem, error in guard let data = dataItem as? Data, let dragInfo = try? JSONDecoder().decode(DragInfo.self, from: data) else { return } handleDrop(with: (dragInfo.tool, dragInfo.url)) } return true }
内容的提问来源于stack exchange,提问作者Keith
相关产品推荐
相关产品推荐

