如何在iOS分享扩展中获取屏幕截图?

5
我已经为我的应用程序创建了一个共享扩展,用户可以通过它创建带有图片的帖子。当从“照片”中选择并分享任何图像时,它能够完美地工作,但是当截屏被直接分享时,共享扩展无法获取它。
我已经编写了用于获取图像的代码。
-(void)fetchImages {
    for (NSExtensionItem *item in self.extensionContext.inputItems) {

        [item.attachments enumerateObjectsUsingBlock:^(NSItemProvider * _Nonnull itemProvider, NSUInteger idx, BOOL * _Nonnull stop) {
            if ([itemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeImage]) {
                [itemProvider loadItemForTypeIdentifier:(NSString *)kUTTypeImage options:nil completionHandler:^(NSData *image, NSError *error) {
                    // You will get Image data here that you can submit to server.
                    [self showAlertWithMessage:[error localizedDescription]];

                    if(image) {
                        [self saveImage:image atIndex:idx];
                    }
                }];
            }
        }];
    }
}

上述方法在viewDidLoad之后调用。当从“照片”中选择任何图像时,它都可以完美显示,但是当立即共享屏幕截图时,我会收到错误提示“无法将项目强制转换为NSData类”。如有任何帮助,不胜感激。谢谢。


可能这些截图不是“kUTTypeImage”类型的。你有检查过吗? - Mumtaz Hussain
2个回答

3

虽然这个问题很早之前就被问过了,但我也遇到了同样的问题。在共享扩展中,当我选中图片/文件/音频/视频时,我能够获取它们,但是当我试图分享截屏时,立即在捕获后就无法检索到截屏数据作为NSData,因为它不是正确的格式,无法显示。经过数小时的努力,我找到了解决方案,你需要检查两个事情:

问题说明: 1- 当截屏时,它的类型不是kUTTypeImage类型,而是public.image类型。因此在提取类型数据时要记住这一点。 2- 其次,您无法将其作为NSData提取,而需要在完成处理程序中将其提取为'id item'。

示例:

// To extract selected files
NSExtensionItem *selectedContent = self.extensionContext.inputItems[0];
// For single selected files, selected content will be at 0 index
NSItemProvider *itemProvider = extensionItem.attachments[0]; // No need to worry about multiple selected files, you can iterate extensionItem.attachments to extract all selected files one by one.
// Now extract all registered **itemTypeIdentifiers** instead of fetching data by providing type by yourself
NSArray *registeredTypeIdentifiers = itemProvider.registeredTypeIdentifiers;
// You can validate before fetching that actually the selected item is of corresponding type
if ([itemProvider hasItemConformingToTypeIdentifier:registeredTypeIdentifiers.firstObject]) {
           // Now fetch data by passing corresponding data type      
          [itemProvider loadItemForTypeIdentifier:registeredTypeIdentifiers.firstObject options:nil completionHandler:^(id<NSSecureCoding> item, NSError *error) {
              if (item) {
                        
                  // For all selected photos/files
                  if([(NSObject*)item isKindOfClass:[NSURL class]]) {
                      NSData *contentData = [NSData dataWithContentsOfURL:(NSURL *)item];
                    // continue working with selected image/file
                  }
                  if([(NSObject*)item isKindOfClass:[UIImage class]]) {
                     NSData  *contentData = UIImagePNGRepresentation((UIImage*)item);
                    // continue working with screenshot data
                  }
                        
              }
          }];
                
}

加油!


我遇到了一个程序相关问题,截图分享的回调函数没有被调用,类似于这个链接中的问题:https://stackoverflow.com/questions/49174303/swift-loaditem-closure-not-running。 - ximmyxiao
你遇到了什么问题,@ximmyxiao?请具体说明,以便我能帮助你解决。因为我在9月5日使用XCode 11.6和iOS 13.6进行测试时,它是正常工作的。 - AQEEL AHMED
感谢 @AQEEL AHMED,我的问题是我在didSelectPost结束时调用了completeRequestReturningItems,因此我的loadItem回调将永远不会被调用,我认为这可能是其他像我一样的人需要注意的重要点 :) - ximmyxiao

0
- (void)loadItemForTypeIdentifier:(NSString *)typeIdentifier options:(nullable NSDictionary *)options completionHandler:(nullable NSItemProviderCompletionHandler)completionHandler;

typedef void (^NSItemProviderCompletionHandler)(__nullable id <NSSecureCoding> item, NSError * __null_unspecified error);

item 可能是多种类型。


这里没有问题。请提出一个问题并提供任何其他可能有帮助的上下文和代码。 - Guy Lowe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接