Apple NSItemProvider类
Apple NSItemProvider类

Apple NSItemProvider类

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/

   

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

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

发表回复

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