13

新しい iOS 8 アプリ拡張機能を使用して共有拡張機能を作成しようとしています。Safari サイトの現在の URL を取得して、UILabel に表示しようとしました。十分に単純です。

私はここでアップルの公式拡張ガイドに取り組んでいまししかし、いくつかのことが期待どおりに機能していません。ベータ版であることはわかっていますが、何か間違ったことをしているだけかもしれません。

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

ディクショナリのオブジェクト内の配列は常に空です。

Apple サイトをシステム メール アプリで共有すると、URL がメッセージに投稿されます。では、拡張機能に URL がないのはなぜですか?

4

7 に答える 7

13

以下、URLの取得方法です。タイプ識別子が kUTTypeURL で、ブロック引数が NSURL であることに注意してください。また、私のようにplistも正しい必要があります。ドキュメントが不足していたため、Apple dev フォーラムの 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;
    }];
}

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>
于 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]; を移動しただけです。他のタスクの最後のブロック内。最終的な作業バージョンは次のようになります (Mavericks OS X 10.9.4 の Xcode 6 ベータ 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共有にも使えるといいのですが。

于 2014-08-22T05:49:58.387 に答える
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 に答える
3

これらの以前の回答はすべて非常に優れていますが、Swiftでこの問題に遭遇したばかりで、NSExtensionContext特にCFStringto変換プロセスで特定のURLを抽出するのは少し面倒だと感じました.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 に答える
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 に答える