SwiftUI Drag&Drop:如何在validateDrop方法中获取被拖拽对象
问题核心原因
validateDrop 方法要求同步返回布尔类型的校验结果,你调用的 itemProvider.loadObject(ofClass:) 是异步加载接口,加载回调执行时,validateDrop 已经提前返回了结果,所以无法在回调里拿到对象做即时校验。
最优解决方案:使用拖拽本地对象实现同步读取
同App进程内的拖拽场景,可以在构造拖拽项时将对象注册为NSItemProvider的本地对象,在validateDrop中直接同步读取,不需要走异步加载流程:
- 首先修改拖拽侧的代码,注册本地对象:
// 你定义Drag的位置代码示例 .onDrag { let playerInstance = // 你的被拖拽Player对象 let provider = NSItemProvider(object: playerInstance) // 注册本地对象,同进程内可直接同步读取 provider.registerObject(playerInstance, visibility: .all) return provider }
- 调整
validateDrop的代码,直接同步读取对象做校验:
func validateDrop(info: DropInfo) -> Bool { print("Drop Validating") print ("Dropping into slot where \(rosterPlayer!.givenName!) \(rosterPlayer!.surname!) is") guard info.hasItemsConforming(to: [PlayerShirtUTT.uti.identifier]), let itemProvider = info.itemProviders(for: [PlayerShirtUTT.uti.identifier]).first, // 直接同步取本地对象,无需等待异步回调 let dragPlayer = itemProvider.localObject as? Player else { return false } // 这里直接做你的校验逻辑 print("拿到拖拽的Player对象:\(dragPlayer.givenName ?? "")") // 返回你的实际校验结果 return true }
跨进程拖拽场景的替代方案
如果你的拖拽需要支持跨App场景,本地对象无法生效,可以调整校验逻辑:
validateDrop阶段只校验UTI类型是否符合,先返回true- 所有业务逻辑校验放在
performDrop方法中执行,如果校验不通过直接返回false,系统会自动判定为drop失败,不会执行后续操作
内容的提问来源于stack exchange,提问作者Andy Davison
相关产品推荐
相关产品推荐

