SwiftUI拖拽onDrag
SwiftUI拖拽onDrag

SwiftUI拖拽onDrag

onDrag 是 SwiftUI 中用于实现拖拽(Drag and Drop)功能的修饰符,它允许将某个视图变成“可以拖拽的内容源”。

基本定义

SwiftUI 中 .onDrag 方法的签名:

func onDrag(_ data: @escaping () -> NSItemProvider) -> some View

它表示:当用户在这个视图上长按并开始拖拽时,提供一个 NSItemProvider,用于系统识别拖动的内容类型(如图像、文字、文件等)。

示例:拖拽图片

Image(nsImage: myImage)
    .onDrag {
        let provider = NSItemProvider(object: myImage)
        return provider
    }

当这张图片上开始拖动,macOS 会调用 .onDrag 中的闭包,将 myImage 封装为一个 NSItemProvider,系统就能识别这个拖拽操作并允许拖到 Finder、桌面或其他接受拖拽的 App。

支持内容类型

1、拖出文本内容:NSString、String:

Text("拖拽文本")
    .onDrag { "hello" }

2、拖出图像:NSImage、UIImage;

3、拖出文件路径:URL(fileURLWithPath:);

4、拖出 PDF:NSData 或 NSFileWrapper;

5、拖出 URL: NSURL:

Text("拖拽 URL")
    .onDrag { NSItemProvider(object: url as NSURL) }

6、拖出多种类型:NSItemProvider 支持多类型加载方式。

.onDrag {
    let provider = NSItemProvider()
    provider.registerDataRepresentation(forTypeIdentifier: UTType.rtf.identifier,visibility: .all) { completion in
        completion(Data, nil)
        return nil
    }
    return provider
}

使用registerDataRepresentation,可以支持富文本RTF、图片、文件、HTML、PDF等多种格式,允许懒加载数据(只有在 drop target真正需要时才生成Data)。

使用示例

1、拖出字符串

Text("拖我一下")
    .onDrag {
        NSItemProvider(object: "Hello World" as NSString)
    }

2、拖出图片

Image(nsImage: image)
    .onDrag {
        NSItemProvider(object: image)
    }

注意事项

1、.onDrag 只能用在 macOS / iPadOS / 支持拖拽的视图上。

2、字符串才能直接用 NSItemProvider(object:)。

3、NSItemProvider(object: attr.string as NSString) 会丢失所有富文本格式,因为 attr.string 只是纯文本。

4、只有 registerDataRepresentation 才能正确提供多媒体/二进制格式。

5、.onDrag 本身不创建文件,只给 Finder 数据,Finder决定要创建一个 .rtf、.txt、.png等文件。

总结

SwiftUI 的 .onDrag 实际上API 的统一封装:

1、macOS:NSDraggingSource + NSPasteboardItemProvider

2、iOS:UIDragInteraction + NSItemProvider

SwiftUI不支持处理拖拽逻辑,只提供一个数据构造回调。

当用户触发拖拽手势时,UIKit / AppKit捕获手势,调用闭包() -> NSItemProvider,系统根据provider 的类型标识符(UTI / UTType),决定拖拽内容支持的目标,系统启动拖拽会话。

.onDrag的唯一职责是,提供一个准确声明内容类型的NSItemProvider,真实拖拽系统由 UIKit / AppKit 驱动。

相关文章

1、Apple NSItemProvider类:https://fangjunyu.com/2025/07/09/apple-nsitemprovider%e7%b1%bb/

   

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开发者。

欢迎加入我们的 微信交流群QQ交流群,交流更多精彩内容!
微信交流群二维码 QQ交流群二维码

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注