You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:23:01