NSItemProvider 是 Apple 提供的一个类,用于在 macOS 和 iOS 上处理拖放(drag & drop)、剪贴板复制粘贴(copy/paste)、文件导入/导出等场景中的数据交换与延迟加载。
NSItemProvider 是一个“数据中转站”,它不直接保存数据,而是保存一种“数据类型 + 获取方式”的组合。
可以把它想象成一个“可以懒加载数据的容器”: 可以包含多种类型的数据(如图像、文本、文件)。
使用场景
例如,在SwiftUI中使用 .onDrop(of: isTargeted:perform:) 捕获目标,实际捕获的是NSItemProvider类型。
.onDrop(of: [.image], isTargeted: $hovering) { providers in
for provider in providers {
provider.loadDataRepresentation(forTypeIdentifier: UTType.image.identifier) { data, error in
if let data = data {
let image = NSImage(data: data)
// 使用 image
}
}
}
return true
}
当拖入一个PNG图片文件,系统返回的是:
NSItemProvider(object: UIImage(named: "photo.png")!)
或者文件拖入时:
NSItemProvider(contentsOf: fileURL)
在获取到NSItemProvider对象后,使用NSItemProvider的方法可以获取data数据,从而实现图片/文件的获取。
常用方法
1、类型检测:hasItemConforming(toTypeIdentifier:),判断是否包含指定类型的数据,适用于macOS 10.10 / iOS 11。
if provider.hasItemConformingToTypeIdentifier(UTType.image.identifier) {
// 支持图像类型
}
2、数据加载:loadFileRepresentation(forTypeIdentifier:),异步方式获取文件的临时本地URL。
provider.loadFileRepresentation(forTypeIdentifier: UTType.image.identifier) { url, error in
if let fileURL = url {
print("获得临时文件URL:\(fileURL)")
// 可以 copy 到沙盒,或者用 QuickLook 预览
}
}
注意:这个文件位于临时目录(例如 /private/var/…/TemporaryItems/),通常只在当前会话中有效。
3、数据加载:loadItem(forTypeIdentifier:options:completionHandler:),加载指定类型的数据(自动类型转换),适用于macOS 10.10 / iOS 11。
provider.loadDataRepresentation(forTypeIdentifier: UTType.image.identifier) { data, error in
if let data = data, let image = NSImage(data: data) {
// 使用 image
}
}
4、数据加载:loadDataRepresentation(forTypeIdentifier:completionHandler:),加载指定类型的原始数据(NSData),适用于macOS 10.13 / iOS 11。
provider.loadObject(ofClass: NSImage.self) { image, error in
if let image = image as? NSImage {
DispatchQueue.main.async {
self.myImage = image
}
}
}
注意:返回的是 Any?,需要强转类型。
5、注册提供器:registerDataRepresentation(forTypeIdentifier:visibility:loadHandler:),注册延迟加载的数据,适用于macOS 10.13 / iOS 11。
let provider = NSItemProvider()
let data = myImage.tiffRepresentation
provider.registerDataRepresentation(forTypeIdentifier: UTType.image.identifier, visibility: .all) { completion in
completion(data, nil)
return nil
}
或者更高级方式:
provider.registerObject(myImage, visibility: .all)
6、提供对象:registerObject(_:visibility:),注册 Swift/Objective-C 对象,如 UIImage、NSString,适用于macOS 10.15 / iOS 13。
7、读取对象:loadObject(ofClass:completionHandler:),直接解码为对象,如 UIImage.self、URL.self,适用于macOS 10.15 / iOS 13。
8、类型列举:registeredTypeIdentifiers,当前可用的 UTI 列表,适用于macOS 10.10 / iOS 11。
let types = provider.registeredTypeIdentifiers
print(types) // [ "public.jpeg", "public.png", "public.image" ... ]
常用类型标识符
1、图片:UTType.image.identifier。
2、PNG:UTType.png.identifier。
3、文本:UTType.plainText.identifier。
4、URL:UTType.url.identifier。
5、文件:UTType.fileURL.identifier。
可以使用 UniformTypeIdentifiers 框架引入这些标识符。
import UniformTypeIdentifiers
UTType相关知识点,可以进一步阅读《Apple类型标识符UTType》。
主要用途
1、拖放(Drag & Drop):拖图片到应用中(.onDrop 中的 providers: [NSItemProvider])。
2、拷贝粘贴:UIPasteboard 和 NSPasteboard 也用 NSItemProvider。
3、文件导入:文件选择器返回的是一个或多个 NSItemProvider。
4、分享扩展:Share Extension 提供的数据通过 NSItemProvider 传递。
NSItemProvider参数
1、visibility
NSItemProvider.Visibility 是一个枚举类型,定义了提供的数据(对象、数据、文件)可以被哪些进程访问。
public enum NSItemProvider.Visibility : Int {
case ownProcess
case team
case all
}
.ownProcess:仅当前 App 内部访问,拖放/分享仅在 App 内,最安全,最快速。
.team:同一开发团队下的 App(含扩展)下互相访问,用于App 和 Extension、App Group,比 .ownProcess 多支持 App Extension。
.all:所有 App,例如拖出到 Finder、邮件、其他 App,适合拖出图片、文件等到系统。
2、options
options 参数([String: Any]? 类型)。
func registerFileRepresentation(
forTypeIdentifier typeIdentifier: String,
visibility: NSItemProvider.Visibility,
options: [AnyHashable : Any]? = nil,
loadHandler: @escaping (@escaping (URL?, Bool, Error?) -> Void) -> Progress?
)
这是一个可选的字典参数,用来传递附加信息,目前 Apple 文档并没有公开所有支持的 key,但以下情况是开发者在实践中遇到过的:
1、NSFileProviderPreferredFilenameKey:String类型,指定拖出文件的建议文件名。
2、NSItemProviderPreferredImageSizeKey:CGSize类型,指定图像类型内容的首选尺寸。
3、NSItemProviderSuggestedNameKey:String类型,建议的文件名称(与 suggestedName 类似)。
4、NSFileProviderTypeDocument:Bool类型,声明是文档类型(非官方)。
使用示例:
provider.registerFileRepresentation(
forTypeIdentifier: UTType.png.identifier,
visibility: .all,
options: [NSFileProviderPreferredFilenameKey: "compressed-image.png"]
) { completion in
completion(localURL, true, nil)
return nil
}
当用户拖拽图片出去时,文件名是指定的”compressed-image.png”。
总结
NSItemProvider 是 Foundation 框架中的类(iOS/macOS 通用),用于在不同App、控件之间传递内容。
支持延迟加载、多类型内容、统一接口。
常见于拖放、剪贴板、分析、文件导入等场景。
相关文章
1、SwiftUI拖放操作onDrop:https://fangjunyu.com/2025/07/04/swiftui%e6%8b%96%e6%94%be%e6%93%8d%e4%bd%9condrop/
2、Apple类型标识符UTType:https://fangjunyu.com/2025/07/05/apple%e7%b1%bb%e5%9e%8b%e6%a0%87%e8%af%86%e7%ac%a6uttype/