13

我正在尝试使用新的 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 支持页面并尝试将其共享到我的扩展程序时,我得到以下值但没有 URL:

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

字典对象内的数组始终为空。

当我与系统邮件应用程序共享苹果网站时,URL 会发布到消息中。那么为什么我的扩展程序中没有 URL?

4

7 回答 7

13

以下是获取网址的方法。请注意,类型标识符是 kUTTypeURL,块参数是 NSURL。此外,plist 也需要像我的一样正确。缺少文档并从Apple 开发论坛上的 number4获得了帮助。(您需要注册并登录才能看到它)。

代码:

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;
    }];
}

信息列表

<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>
于 2014-06-15T01:02:53.020 回答
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]; 在其他任务结束时的块内。最终的工作版本如下所示(Xcode 6 beta 5 on Mavericks OS X 10.9.4):

- (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];

}

我希望它也适用于 URL 共享。

于 2014-08-22T05:49:58.387 回答
3

所有这些先前的答案都非常好,但我只是在 Swift 中遇到了这个问题,觉得从给定的 URL 中提取 URL 有点麻烦,NSExtensionContext尤其是在CFString转换过程中,并且in没有在主线程中执行String的事实.completionHandlerloadItemForTypeIdentifier

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子类中像这样简单地使用它:

self.extensionContext?.extractURL({ (url) -> Void in
    self.urlLabel.text = url?.absoluteString
    println(url?.absoluteString)
})
于 2015-04-24T12:39:03.620 回答
3

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

- (void)beginRequestWithExtensionContext:(NSExtensionContext *)context

在尝试获取NSExtensionContext. 它甚至提供方法中的上下文作为context参数。

本文件对此进行了概述。

于 2014-06-06T21:08:40.380 回答
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
                        }
                    }
                })
            }
        }
    }
}
于 2015-09-16T12:06:27.603 回答
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 的第二个扩展会话。

于 2014-06-13T06:36:46.387 回答
1
let itemProvider = item.attachments?.first as! NSItemProvider
itemProvider.loadItemForTypeIdentifier("public.url", options: nil) { (object, error) -> Void in
     println(object)
}

所以 println : http ://detail.m.tmall.com/item.htm?id=38131345289&spm=a2147.7632989.mainList.5

于 2015-06-02T11:54:21.710 回答