在IOS8 beta中共享扩展

我正在尝试使用新的iOS 8应用程序扩展程序创build共享扩展程序。 我试图得到一个Safari网站的当前url显示在一个UILabel。 很简单。

我正在从苹果的官方扩展指南https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/Share.html#//apple_ref/doc/uid/TP40014214-CH12-SW1但有些事情并不像预期的那样工作。 我知道这只是在testing,但也许我只是做错了什么。

这里是我的代码来获取从扩展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; } 

这是我的Extension的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?

以下是如何获得url。 注意types标识符是kUTTypeURL,块参数是NSURL。 另外,plist也需要像我的一样正确。 缺less文档,并从Apple开发论坛的第4位获得帮助。 (你需要注册并login才能看到)。

码:

 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> 

我已经为自己解决了。 我正在尝试与共享图像。

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

我希望它也可以用于URL共享。

你的扩展视图控制器应该采用NSExtensionRequestHandling协议。 其中一个协议的方法是:

 - (void)beginRequestWithExtensionContext:(NSExtensionContext *)context 

在尝试获取NSExtensionContext之前,您应该等待这个被调用。 它甚至提供方法中的context作为context参数。

这是在这个文件中概述。

所有这些以前的答案是真的很好,但我刚刚在这个问题在Swift中,并认为从一个给定的NSExtensionContext特别是在CFStringString转换过程提取url是有点不太清楚, NSExtensionContext中的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子类中使用它:

 self.extensionContext?.extractURL({ (url) -> Void in self.urlLabel.text = url?.absoluteString println(url?.absoluteString) }) 

其他答案都是复杂和不完整的。 他们只能在Safari中工作,不能在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 } } }) } } } } 

您需要查找types为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的第二个扩展会话。

 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