在IOS8测试版中共享扩展

时间:2014-06-05 09:08:25

标签: ios ios8 ios-app-extension

我正在尝试使用新的iOS 8应用扩展程序创建共享扩展程序。我试图获取Safari网站的当前URL以在UILabel中显示它。很简单。

我正在通过苹果公司的官方扩展指南https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/Share.html#//apple_ref/doc/uid/TP40014214-CH12-SW1工作,但有些事情没有按预期工作。我知道它只是在测试中,但也许我只是做错了。

这是我的代码,用于从扩展ViewController中的safari获取URL:

-(void)viewDidAppear:(BOOL)animated{
NSExtensionContext *myExtensionContext = [self extensionContext];
NSArray *inputItems = [myExtensionContext inputItems];
NSMutableString* mutableString = [[NSMutableString alloc]init];
for(NSExtensionItem* item in inputItems){
    NSMutableString* temp = [NSMutableString stringWithFormat:@"%@, %@, %lu, 
           %lu - ",item.attributedTitle,[item.attributedContentText string],
           (unsigned long)[item.userInfo count],[item.attachments count]];

    for(NSString* key in [item.userInfo allKeys]){
        NSArray* array = [item.userInfo objectForKey:@"NSExtensionItemAttachmentsKey"];
        [temp appendString:[NSString stringWithFormat:@" in array:%lu@",[array count]]];   
    }
    [mutableString appendString:temp];
}
self.myLabel.text = mutableString;
}

这是我的扩展程序的Info.plist文件的内容:

<dict>
    <key>NSExtensionMainStoryboard</key>
    <string>MainInterface</string>
    <key>NSExtensionPointIdentifier</key>
    <string>com.apple.share-services</string>
    <key>NSExtensionActivationRule</key>
    <dict>
        <key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
        <integer>200</integer>
    </dict>
</dict>

当我访问Safari中的苹果iPod支持页面并尝试将其分享到我的扩展程序时,我得到以下值但没有网址:

item.attributedTitle = (null)
item.attributedContentText = "iPod - Apple Support"
item.userInfo.count = 2 (two keys: NSExtensionAttributedContentTextKey and
    NSExtensionItemAttachmentsKey)
item.attachments.count = 0

字典对象内的数组总是空的。

当我与系统邮件应用程序共享apple站点时,URL将发布到邮件中。那么为什么我的扩展程序中没有URL?

7 个答案:

答案 0 :(得分:13)

以下是如何获取网址的方法。请注意,类型标识符是kUTTypeURL,块参数是NSURL。此外,plist也需要像我的一样正确。文档缺乏并得到number4 on the Apple dev forums的帮助。 (您需要注册并登录才能看到它)。

代码:

NSExtensionItem *item = self.extensionContext.inputItems.firstObject;
NSItemProvider *itemProvider = item.attachments.firstObject;
if ([itemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeURL]) {
    [itemProvider loadItemForTypeIdentifier:(NSString *)kUTTypeURL options:nil completionHandler:^(NSURL *url, NSError *error) {
        self.urlString = url.absoluteString;
    }];
}

的Info.plist

<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>

答案 1 :(得分:9)

我已经为自己解决了这个问题。我正在尝试使用“共享图像”。

- (void)didSelectPost {


// This is called after the user selects Post. Do the upload of contentText and/or NSExtensionContext attachments.

// Inform the host that we're done, so it un-blocks its UI. Note: Alternatively you could call super's -didSelectPost, which will similarly complete the extension context.

// Verify that we have a valid NSExtensionItem
NSExtensionItem *imageItem = [self.extensionContext.inputItems firstObject];
if(!imageItem){
    return;
}

// Verify that we have a valid NSItemProvider
NSItemProvider *imageItemProvider = [[imageItem attachments] firstObject];
if(!imageItemProvider){
    return;
}

// Look for an image inside the NSItemProvider
if([imageItemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeImage]){
    [imageItemProvider loadItemForTypeIdentifier:(NSString *)kUTTypeImage options:nil completionHandler:^(UIImage *image, NSError *error) {
        if(image){
            NSLog(@"image %@", image);
            // do your stuff here...

        }
    }];
    }
// this line should not be here. Cos it's called before the block finishes.
// and this is why the console log or any other task won't work inside the block
[self.extensionContext completeRequestReturningItems:nil completionHandler:nil];

}

所以我所做的只是移动了[self.extensionContext completeRequestReturningItems:nil completionHandler:nil];在其他任务结束时的块内。最终的工作版本看起来像这样(Mavericks OS X 10.9.4上的Xcode 6 beta 5):

- (void)didSelectPost {


// This is called after the user selects Post. Do the upload of contentText and/or NSExtensionContext attachments.

// Inform the host that we're done, so it un-blocks its UI. Note: Alternatively you could call super's -didSelectPost, which will similarly complete the extension context.

// Verify that we have a valid NSExtensionItem
NSExtensionItem *imageItem = [self.extensionContext.inputItems firstObject];
if(!imageItem){
    return;
}

// Verify that we have a valid NSItemProvider
NSItemProvider *imageItemProvider = [[imageItem attachments] firstObject];
if(!imageItemProvider){
    return;
}

// Look for an image inside the NSItemProvider
if([imageItemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeImage]){
    [imageItemProvider loadItemForTypeIdentifier:(NSString *)kUTTypeImage options:nil completionHandler:^(UIImage *image, NSError *error) {
        if(image){
            NSLog(@"image %@", image);
            // do your stuff here...

            // complete and return
            [self.extensionContext completeRequestReturningItems:nil completionHandler:nil];       
        }
    }];
    }
// this line should not be here. Cos it's called before the block finishes.
// and this is why the console log or any other task won't work inside the block
// [self.extensionContext completeRequestReturningItems:nil completionHandler:nil];

}

我希望它也适用于网址共享。

答案 2 :(得分:3)

您的扩展程序视图控制器应采用NSExtensionRequestHandling协议。该协议的方法之一是:

- (void)beginRequestWithExtensionContext:(NSExtensionContext *)context

在尝试获取NSExtensionContext之前,您应该等待此调用。它甚至将方法中的上下文作为context参数提供。

this document中列出了这一点。

答案 3 :(得分:3)

所有这些以前的答案都非常好,但我刚刚在Swift中遇到了这个问题,并认为从给定NSExtensionContext中提取网址有点琐碎,特别是在CFString到{{转换过程以及String中的completionHandler未在主线程中执行的事实。

loadItemForTypeIdentifier

这样你现在可以在你的import MobileCoreServices extension NSExtensionContext { private var kTypeURL:String { get { return kUTTypeURL as NSString as String } } func extractURL(completion: ((url:NSURL?) -> Void)?) -> Void { var processed:Bool = false for item in self.inputItems ?? [] { if let item = item as? NSExtensionItem, let attachments = item.attachments, let provider = attachments.first as? NSItemProvider where provider.hasItemConformingToTypeIdentifier(kTypeURL) == true { provider.loadItemForTypeIdentifier(kTypeURL, options: nil, completionHandler: { (output, error) -> Void in dispatch_async(dispatch_get_main_queue(), { () -> Void in processed = true if let url = output as? NSURL { completion?(url: url) } else { completion?(url: nil) } }) }) } } // make sure the completion block is called even if no url could be extracted if (processed == false) { completion?(url: nil) } } } 子类中使用它:

UIViewController

答案 4 :(得分:3)

其他答案都很复杂且不完整。它们仅适用于Safari,不适用于Google Chrome。这适用于Google Chrome和Safari:

override func viewDidLoad() {
    super.viewDidLoad()

    for item in extensionContext!.inputItems {
        if let attachments = item.attachments {
            for itemProvider in attachments! {
                itemProvider.loadItemForTypeIdentifier("public.url", options: nil, completionHandler: { (object, error) -> Void in
                    if object != nil {
                        if let url = object as? NSURL {
                        print(url.absoluteString) //This is your URL
                        }
                    }
                })
            }
        }
    }
}

答案 5 :(得分:1)

您需要查找kUTTypePropertyList类型的附件。通过扩展程序中第一个扩展项的第一个附件执行类似的操作:

NSExtensionItem *extensionItem = self.extensionContext.extensionItems.firstObject;
NSItemProvider *itemProvider =  self.extensionItem.attachments.firstObject;
[itemProvider loadItemForTypeIdentifier:kUTTypePropertyList options:nil
  completionHandler:^(NSDictionary *item, NSError *error) {
   // Unpack items from "item" in here
}];

您还需要设置一些JavaScript来从DOM中获取所需的所有数据。有关详细信息,请参阅WWDC 14中的第二个扩展会话。

答案 6 :(得分:1)

let itemProvider = item.attachments?.first as! NSItemProvider
itemProvider.loadItemForTypeIdentifier("public.url", options: nil) { (object, error) -> Void in
     println(object)
}

所以println: http://localhost:804/cgi-bin/ex7.py