Handle NSItemProvider data types in Share Extension (Swift)
There's a new API that is used in examples, canLoadObject and 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
As far as I tested, in some cases, you will have a Data
in data
. So, you may need to write something like this if you do not want to write an Objective-C wrapper for this method:
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
}
//...
}
}
(Not tested, you may need to fix some parts.)
In Objective-C, you can pass an Objective-C block taking (UIImage *item, NSError *error)
to the completionHandler
of loadItemForTypeIdentifier:options:completionHandler:
. In such case, the item provider tries to convert all sorts image data into 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.
So, if you do not mind writing some Objective-C wrapper, you can write something like this:
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"
And use it from Swift as:
if attachment.hasItemConformingToTypeIdentifier(IMAGE_TYPE) {
attachment.loadImage(forTypeIdentifier: IMAGE_TYPE, options: nil) { myImage, error in
//...
}
}
In my opinion, Apple should provide this sort of type-safe extension of NSItemProvider
, you can write a feature request using Apple's Bug Reporter.