iOS UICollectionView拖拽至自定义View无响应,求Model类型标识
解决UICollectionView拖拽到CustomView无响应的问题
你遇到的核心问题确实出在类型标识(UTI)的配置以及NSItemProviderWriting/Reading的空实现上,下面一步步帮你修复:
1. 给自定义Model设置有效的UTI
首先要为UserClass定义一个唯一的Uniform Type Identifier(UTI),这是系统识别拖拽数据类型的关键。通常我们用应用Bundle ID加类型名称来确保唯一性:
class UserClass: NSObject, NSItemProviderWriting, NSItemProviderReading { // 定义自定义UTI,替换成你的实际Bundle ID前缀 static let typeIdentifier = "com.yourcompany.UserClass" // 存储业务数据 let someData: String required init(someData: String) { self.someData = someData super.init() } // MARK: - NSItemProviderReading static var readableTypeIdentifiersForItemProvider: [String] { return [typeIdentifier] // 返回自定义UTI,让系统能识别可接收的类型 } static func object(withItemProviderData data: Data, typeIdentifier: String) throws -> Self { // 反序列化:把Data转回UserClass实例 guard let decodedUser = try? JSONDecoder().decode(UserClass.self, from: data) else { throw NSError(domain: "UserClassDecoding", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to decode UserClass"]) } return decodedUser as! Self } // MARK: - NSItemProviderWriting static var writableTypeIdentifiersForItemProvider: [String] { return [typeIdentifier] // 返回自定义UTI,让系统能识别可拖拽的类型 } func loadData(withTypeIdentifier typeIdentifier: String, forItemProviderCompletionHandler completionHandler: @escaping (Data?, Error?) -> Void) -> Progress? { // 序列化:把UserClass实例转成Data do { let data = try JSONEncoder().encode(self) completionHandler(data, nil) } catch { completionHandler(nil, error) } return nil } } // 让UserClass支持Codable,方便序列化/反序列化 extension UserClass: Codable {}
2. 修复Drop Interaction的canHandle方法
现在在你的CustomView的UIDropInteractionDelegate实现中,检查session是否包含我们定义的UTI:
func dropInteraction(_ interaction: UIDropInteraction, canHandle session: UIDropSession) -> Bool { // 检查拖拽会话中是否有符合自定义UTI的item return session.hasItemsConforming(toTypeIdentifiers: [UserClass.typeIdentifier]) }
为什么之前的代码不工作?
- 你之前的
readableTypeIdentifiersForItemProvider和writableTypeIdentifiersForItemProvider都返回空数组,系统完全无法识别这个拖拽数据的类型,自然不会触发后续的drop回调。 - 序列化/反序列化方法是空实现,即使类型标识正确,也无法完成数据的传递,后续流程会直接中断。
额外提示
如果需要同时支持系统内置类型(比如文本),可以在readable/writableTypeIdentifiersForItemProvider数组中添加对应的UTI,比如kUTTypePlainText as String(记得导入MobileCoreServices框架)。
内容的提问来源于stack exchange,提问作者Ivan Cantarino
相关产品推荐
相关产品推荐

