iOS 8共享扩展loadItemForTypeIdentifier:options:completionHandler:完成关闭未执行

时间:2014-06-16 02:29:35

标签: share swift ios8 ios-app-extension

我正在使用 loadItemForTypeIdentifier:options:completionHandler:NSItemProvider对象上的方法,用于通过iOS 8中的Share扩展从Safari中提取URL。

在Objective-C中,此代码和工作以及块运行。

[itemProvider loadItemForTypeIdentifier:(@"public.url" options:nil completionHandler:^(NSURL *url, NSError *error) {
    //My code
}];

在Swift中,它看起来非常相似,但是关闭并没有运行。此外,itemProvider.hasItemConformingToTypeIdentifier("public.url")会返回YES,因此必须有一个有效的对象来解析itemProvider内的网址。

itemProvider.loadItemForTypeIdentifier("public.url", options: nil, completionHandler: { (urlItem, error) in
    //My code
})

Info.plist NSExtension部分与Objective-C和Swift版本完全相同,如下所示:

<key>NSExtension</key>
<dict>
    <key>NSExtensionAttributes</key>
    <dict>
        <key>NSExtensionActivationRule</key>
        <dict>
            <key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
            <integer>1</integer>
        </dict>
        <key>NSExtensionPointName</key>
        <string>com.apple.share-services</string>
        <key>NSExtensionPointVersion</key>
        <string>1.0</string>
    </dict>
    <key>NSExtensionPointIdentifier</key>
    <string>com.apple.share-services</string>
    <key>NSExtensionMainStoryboard</key>
    <string>MainInterface</string>
</dict>

我做错了什么?

6 个答案:

答案 0 :(得分:10)

呼叫

self.extensionContext!.completeRequestReturningItems([], completionHandler: nil) 

在completionHandler结束时而不是在didSelectPost()结束时调用它

答案 1 :(得分:5)

由于必须在调用所有completionHandler之后调用completeRequestReturningItems,因此以下是我的工作。

 s.public_header_files = 'AFNetworking/*.h'
  s.source_files = 'AFNetworking/AFNetworking.h'

  s.subspec 'Serialization' do |ss|
    ss.source_files = 'AFNetworking/AFURL{Request,Response}Serialization.{h,m}'
    ss.ios.frameworks = 'MobileCoreServices', 'CoreGraphics'
    ss.osx.frameworks = 'CoreServices'
  end

  s.subspec 'Security' do |ss|
    ss.source_files = 'AFNetworking/AFSecurityPolicy.{h,m}'
    ss.frameworks = 'Security'
  end

  s.subspec 'Reachability' do |ss|
    ss.source_files = 'AFNetworking/AFNetworkReachabilityManager.{h,m}'
    ss.frameworks = 'SystemConfiguration'
  end

答案 2 :(得分:4)

答案 3 :(得分:0)

过去几周我一直在争论这个问题,并最终找到了这个问题。我与Objective C或Swift无关,它似乎只是Apple代码中的一个错误。

似乎(在iOS 8.0中),只有在使用自己的UIViewController子类时才会调用完成块。如果您使用的是SLComposeServiceViewController的子类,则不会调用完成块。

这真的很烦人,因为默认情况下,XCode会为您创建一个ShareViewController,其子类为SLComposeServiceViewController。要解决此问题,您只需修改ShareViewController以继承UIViewController。这仍然可以访问extensionContext属性,但您显然会失去所有不错的标准功能,并且必须从头开始实现您的用户界面。

我已经向Apple提交了雷达,但尚未得到答复。希望这将在未来的更新中得到修复。

答案 4 :(得分:0)

我从来没有管理completionHandler正常工作,没有用户界面的Share扩展(在这种情况下扩展&#39; s类是NSObject的子类)。

尽管[itemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeURL]返回YES,但在设备或模拟器上永远不会调用completionHandler。

在尝试不同的方法后,我最终得到了基于javascript将URL传递回扩展的解决方法(抱歉,因为我使用ObjC而不是Swift作为我的例子)。

Info.plist NSExtension部分:

<key>NSExtension</key>
<dict>
    <key>NSExtensionAttributes</key>
    <dict>
        <key>NSExtensionActivationRule</key>
        <dict>
            <key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
            <integer>1</integer>
        </dict>
        <key>NSExtensionJavaScriptPreprocessingFile</key>
        <string>Action</string>
    </dict>
    <key>NSExtensionPointIdentifier</key>
    <string>com.apple.services</string>
    <key>NSExtensionPrincipalClass</key>
    <string>ActionRequestHandler</string>
</dict>

Javascript Action.js文件:

var Action = function() {};
Action.prototype = {
    run: function(arguments) {
        arguments.completionFunction({ "currentURL" : window.location.href })
    },
    finalize: function(arguments) {
    }
};
var ExtensionPreprocessingJS = new Action

ActionRequestHandler.h头文件:

@interface ActionRequestHandler : NSObject <NSExtensionRequestHandling>

@end

ActionRequestHandler.m基于默认操作扩展模板:

#import "ActionRequestHandler.h"
#import <MobileCoreServices/MobileCoreServices.h>

@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

希望它可以帮助某人节省几个小时来完成握手问题。

答案 5 :(得分:0)

我的iOS 12.1中有相同的问题。我在打电话

loadItemForTypeIdentifier:kUTTypeData 

代替kUTTypeImage等。它对我有用。