处理 Share Extension 中的 NSItemProvider 数据类型 (Swift)

Handle NSItemProvider data types in Share Extension (Swift)

我在 Swift (3) 中遇到 Share Extension 编程问题。
我的主要问题是 NSItemProvider.
data 类型的处理 问题在于:根据我从中启动扩展程序的应用程序,我会得到不同类型的数据。例如:
我告诉应用程序:

let IMAGE_TYPE = kUTTypeImage as String
if attachment.hasItemConformingToTypeIdentifier(IMAGE_TYPE){
     attachment.loadItem(forTypeIdentifier: IMAGE_TYPE, options: nil){ data, error in
     ...
}

(注:附件类型为NSItemProvider)

从照片应用程序执行时,data 是一个 URL,所以我从中创建一个 UIImage 并继续。
问题是,对于某些应用程序,data 已经是一个 UIImage,我找不到如何区分大小写。
最好的办法可能是检查 data 对象的数据类型,但至少对我来说这不是微不足道的。
在此先感谢您的帮助!

据我测试,在某些情况下,你会在 data 中有一个 Data。因此,如果您不想为此方法编写 Objective-C 包装器,则可能需要编写如下内容:

if attachment.hasItemConformingToTypeIdentifier(IMAGE_TYPE) {
    attachment.loadItem(forTypeIdentifier: IMAGE_TYPE, options: nil) { data, error in
        let myImage: UIImage?
        switch data {
        case let image as UIImage:
            myImage = image
        case let data as Data:
            myImage = UIImage(data: data)
        case let url as URL:
            myImage = UIImage(contentsOfFile: url.path)
        default:
            //There may be other cases...
            print("Unexpected data:", type(of: data))
            myImage = nil
        }
        //...
    }
}

(未测试,您可能需要修复一些部分。)


在Objective-C中,你可以将Objective-C块传递给loadItemForTypeIdentifier:options:completionHandler:completionHandler(UIImage *item, NSError *error)。在这种情况下,项目提供者会尝试将所有类型的图像数据转换为 UIImage.

NSItemProviderCompletionHandler

Discussion

...

item

The item to be loaded. When specifying your block, set the type of this parameter to the specific data type you want. ... The item provider attempts to coerce the data to the class you specify.

所以,如果你不介意写一些 Objective-C 包装器,你可以这样写:

NSItemProvider+Swift.h:

@import UIKit;

typedef void (^NSItemProviderCompletionHandlerForImage)(UIImage *image, NSError *error);

@interface NSItemProvider(Swift)
- (void)loadImageForTypeIdentifier:(NSString *)typeIdentifier
                          options:(NSDictionary *)options
                completionHandler:(NSItemProviderCompletionHandlerForImage)completionHandler;
@end

NSItemProvider+Swift.m:

#import "NSItemProvider+Swift.h"

@implementation  NSItemProvider(Swift)

- (void)loadImageForTypeIdentifier:(NSString *)typeIdentifier
                           options:(NSDictionary *)options
                 completionHandler:(NSItemProviderCompletionHandlerForImage)completionHandler {
    [self loadItemForTypeIdentifier:typeIdentifier
                            options:options
                  completionHandler:completionHandler];
}

@end

{YourProject}-桥接-Header.h:

#import "NSItemProvider+Swift.h"

并将其从 Swift 用作:

    if attachment.hasItemConformingToTypeIdentifier(IMAGE_TYPE) {
        attachment.loadImage(forTypeIdentifier: IMAGE_TYPE, options: nil) { myImage, error in
            //...
        }
    }

在我看来,Apple 应该提供 NSItemProvider 这种类型安全的扩展,您可以使用 Apple 的 Bug Reporter.

编写功能请求

示例中使用了一个新的 API,canLoadObject 和 loadObject

if (itemProvider.canLoadObject(ofClass: UIImage.self)) {
            itemProvider.loadObject(ofClass: UIImage.self, completionHandler: {
                (data, error) in
                print("==== adding image \(image) as note, error=\(error)")
})

https://developer.apple.com/documentation/uikit/drag_and_drop/data_delivery_with_drag_and_drop