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

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.

问题原因

  1. try? JSONEncoder().encode(draggedData)可能返回nil(比如枚举Tools未正确实现Codable协议),导致NSItemProvider无有效数据;
  2. 自定义的typeIdentifier需为合法的UTI(统一类型标识符),不能随意使用"xxx"这类无效值;
  3. 直接传递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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 04:56:37