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

Posted

技术标签:

【中文标题】在 Share Extension (Swift) 中处理 NSItemProvider 数据类型【英文标题】:Handle NSItemProvider data types in Share Extension (Swift) 【发布时间】:2017-03-04 01:19:19 【问题描述】:

我对 Swift 中的 Share Extension 编程有疑问 (3)。 我的主要问题是处理 NSItemProviderdata 类型。 这是问题所在:根据我启动扩展程序的应用程序,我会得到不同类型的数据。例如: 我告诉应用程序:

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 对象的数据类型,但至少对我来说这不是微不足道的。 提前感谢您的帮助!

【问题讨论】:

【参考方案1】:

据我测试,在某些情况下,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 中,您可以将带有 (UIImage *item, NSError *error) 的 Objective-C 块传递给 loadItemForTypeIdentifier:options:completionHandler:completionHandler。在这种情况下,项目提供者会尝试将各种图像数据转换为UIImage

NSItemProviderCompletionHandler

讨论

...

项目

要加载的项目。指定块时,将此参数的类型设置为您想要的特定数据类型。 ...项目提供者尝试将数据强制转换为您指定的类。

所以,如果您不介意编写一些 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-Bridging-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 编写功能请求。

【讨论】:

非常感谢,太完美了! 尝试了其他所有方法,这是有效的。【参考方案2】:

在示例中使用了一个新的 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

【讨论】:

以上是关于在 Share Extension (Swift) 中处理 NSItemProvider 数据类型的主要内容,如果未能解决你的问题,请参考以下文章

App Extensions篇之Share Extension

iOS9 Share Extension 无法在 Xcode 上调试

来自 Share Extension 的 Safari 截图

错误:无法打开扩展控制文件“/usr/pgsql-9.6/share/extension/postgis.control”:没有这样的文件或目录

iOS扩展开发攻略Share Extension

在为 Release 编译时,如何让 React Native 将 JS 包放入 Share Extension 中?