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

SwiftUI拖拽功能在iOS模拟器正常,Mac Catalyst版本失效排查

Mac Catalyst中SwiftUI拖拽放置失败的原因及解决办法

问题描述

我在SwiftUI应用中实现了拖拽功能,该功能在iOS模拟器中运行完全正常,但在Mac Catalyst版本中无法正常工作:拖拽手势可被识别,但放置操作执行失败。

原实现代码

struct ContentView: View {
    @State private var items = ["Item 1", "Item 2", "Item 3"]

    var body: some View {
        ScrollView {
            LazyVStack {
                ForEach(items, id: \.self) { item in
                    Text(item)
                        .padding()
                        .background(Color.blue)
                        .cornerRadius(8)
                        .foregroundColor(.white)
                        .onDrag {
                            NSItemProvider(object: item as NSString)
                        }
                }
            }
        }
        .onDrop(of: ["public.text"], delegate: CustomDropDelegate(items: $items))
    }
}

struct CustomDropDelegate: DropDelegate {
    @Binding var items: [String]

    func performDrop(info: DropInfo) -> Bool {
        guard let item = info.itemProviders(for: ["public.text"]).first else { return false }
        item.loadItem(forTypeIdentifier: "public.text", options: nil) { (data, error) in
            DispatchQueue.main.async {
                if let textData = data as? Data, let text = String(data: textData, encoding: .utf8) {
                    self.items.append(text)
                }
            }
        }
        return true
    }
}

原因分析

Mac Catalyst和iOS对NSItemProvider处理public.text类型数据的逻辑存在差异:

  • iOS上,通过NSItemProvider(object: NSString)创建的提供者,加载数据时会以Data类型返回
  • 但在Mac Catalyst中,相同代码会直接返回NSString实例,原代码只处理了Data的情况,导致无法解析出文本,放置操作没有实际效果

解决办法

方案1:扩展数据解析逻辑,兼容两种数据类型

修改CustomDropDelegate的performDrop方法,同时支持直接获取NSString和Data转String的情况:

struct CustomDropDelegate: DropDelegate {
    @Binding var items: [String]

    func performDrop(info: DropInfo) -> Bool {
        guard let item = info.itemProviders(for: ["public.text"]).first else { return false }
        item.loadItem(forTypeIdentifier: "public.text", options: nil) { (data, error) in
            DispatchQueue.main.async {
                // 优先处理Mac Catalyst下的NSString情况
                if let text = data as? NSString {
                    self.items.append(text as String)
                } 
                // 兼容iOS下的Data情况
                else if let textData = data as? Data, let text = String(data: textData, encoding: .utf8) {
                    self.items.append(text)
                }
            }
        }
        return true
    }
}

方案2:拖拽时强制指定数据格式

在onDrag闭包中,强制让NSItemProvider以Data形式提供数据,统一iOS和Mac Catalyst的处理逻辑:

.onDrag {
    let itemProvider = NSItemProvider(object: item as NSString)
    // 注册Data格式的表示,确保跨平台一致
    itemProvider.registerDataRepresentation(forTypeIdentifier: "public.text", visibility: .all) { completion in
        completion(item.data(using: .utf8), nil)
        return nil
    }
    return itemProvider
}

这两种方案都能解决Mac Catalyst下放置操作失效的问题,可根据需求选择其中一种。

内容的提问来源于stack exchange,提问作者János

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 13:32:35