macOS SwiftUI跨视图拖拽String时NSItemProvider加载NSString报错如何解决
问题结论
这个是macOS平台NSItemProvider针对字符串类型处理的已知系统Bug,不是你的实现逻辑问题。相同代码在iOS/iPadOS可正常运行,是因为两个平台对NSString的类型桥接和ItemProvider加载逻辑实现不一致,URL类型没有出现问题是因为该类型的加载适配在两个平台是统一的。
可行解决方案
方案1:通过UTType标识符加载数据再转字符串(推荐,支持跨App拖拽字符串)
替换onDrop中的loadObject(ofClass:)方法,改用底层的loadItem(forTypeIdentifier:options:)接口解析内容,代码如下:
ViewB() .onDrop(of: [.plainText], isTargeted: nil, perform: { providers, location in guard let provider = providers.first, provider.hasItemConformingToTypeIdentifier(UTType.plainText.identifier) else { return false } provider.loadItem(forTypeIdentifier: UTType.plainText.identifier, options: nil) { item, error in DispatchQueue.main.async { // macOS下拖拽字符串会返回Data或String两种类型,做兼容判断即可 var droppedText: String? if let textData = item as? Data { droppedText = String(data: textData, encoding: .utf8) } else if let rawText = item as? String { droppedText = rawText } if let text = droppedText { print("Dropped: \(text)") // 后续业务逻辑 } else { print("Parse error: \(error?.localizedDescription ?? "unknown")") } } } return true })
方案2:自定义UTType传递字符串(仅适用App内部拖拽场景)
如果你的拖拽场景仅在App内部使用,不需要和其他App交互,可以自定义UTType来传递字符串,绕开系统对plainText类型的加载bug:
- 在项目Info.plist中注册自定义UTType
- 拖拽时用自定义UTType初始化NSItemProvider
- Drop时按自定义UTType加载即可,逻辑和URL类型的拖拽完全一致
内容的提问来源于stack exchange,提问作者Marcos Tanaka
相关产品推荐
相关产品推荐

