I\'m using the loadItemForTypeIdentifier:options:completionHandler: method on an NSItemProvider object to extract a url from Safari via a Share extension in iOS 8.
I was never managed completionHandler to work properly for Share extension with no user interface (in such case extension's class is a subclass on NSObject).
Despite the [itemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeURL]
returns YES
the completionHandler is never called both on the device or simulator.
After trying different approaches I ended up with workaround based on javascript passing URL back to extension (sorry as I use ObjC not Swift for my example).
Info.plist
NSExtension portion:
NSExtension
NSExtensionAttributes
NSExtensionActivationRule
NSExtensionActivationSupportsWebURLWithMaxCount
1
NSExtensionJavaScriptPreprocessingFile
Action
NSExtensionPointIdentifier
com.apple.services
NSExtensionPrincipalClass
ActionRequestHandler
Javascript Action.js
file:
var Action = function() {};
Action.prototype = {
run: function(arguments) {
arguments.completionFunction({ "currentURL" : window.location.href })
},
finalize: function(arguments) {
}
};
var ExtensionPreprocessingJS = new Action
ActionRequestHandler.h
header file:
@interface ActionRequestHandler : NSObject
@end
ActionRequestHandler.m
based on default Action extension template:
#import "ActionRequestHandler.h"
#import
@interface ActionRequestHandler ()
@property (nonatomic, strong) NSExtensionContext *extensionContext;
@end
@implementation ActionRequestHandler
- (void)beginRequestWithExtensionContext:(NSExtensionContext *)context {
// Do not call super in an Action extension with no user interface
self.extensionContext = context;
BOOL found = NO;
// Find the item containing the results from the JavaScript preprocessing.
for (NSExtensionItem *item in self.extensionContext.inputItems) {
for (NSItemProvider *itemProvider in item.attachments) {
if ([itemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypePropertyList]) {
[itemProvider loadItemForTypeIdentifier:(NSString *)kUTTypePropertyList options:nil completionHandler:^(NSDictionary *dictionary, NSError *error) {
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self itemLoadCompletedWithPreprocessingResults:dictionary[NSExtensionJavaScriptPreprocessingResultsKey]];
}];
}];
found = YES;
}
break;
}
if (found) {
break;
}
}
if (!found) {
// We did not find anything - signal that we're done
[self.extensionContext completeRequestReturningItems:@[] completionHandler:nil];
// Don't hold on to this after we finished with it
self.extensionContext = nil;
}
}
- (void)itemLoadCompletedWithPreprocessingResults:(NSDictionary *)javaScriptPreprocessingResults
{
// Get the URL
if ([javaScriptPreprocessingResults[@"currentURL"] length] != 0) {
NSLog(@"*** URL: %@", javaScriptPreprocessingResults[@"currentURL"]);
}
// Signal that we're done
[self.extensionContext completeRequestReturningItems:@[] completionHandler:nil];
// Don't hold on to this after we finished with it
self.extensionContext = nil;
}
@end
Hope it will help somebody to save couple of hours struggling with the completionHandler issue.