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

Posted

技术标签:

【中文标题】如何在 iOS 共享扩展中获取屏幕截图?【英文标题】:How to fetch screenshot in iOS Share Extension? 【发布时间】:2018-12-22 14:13:56 【问题描述】:

我为我的应用创建了一个共享扩展,用户可以通过它创建带有图片的帖子。 It works perfectly well when any image from "Photos" is selected and shared but when a screenshot is taken and directly shared, the share extension is not able to fetch it.

我已经编写了用于获取图像的代码。

-(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”类型。你检查了吗? 【参考方案1】:

虽然这个问题很久以前就被问过了,但我也遇到了同样的问题。在共享扩展中,我能够在选择照片/文件时获取图像/文件/音频/视频,但是当我尝试在捕获后立即共享屏幕截图时,我无法将屏幕截图数据检索为 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
                  
                        
              
          ];
                

干杯!

【讨论】:

还有一个截图分享回调不是这样调用的***.com/questions/49174303/… 你遇到了什么问题@ximmyxiao?请具体说明,以便我可以帮助您。因为当我在 9 月 5 日使用 XCode 11.6 和 ios 13.6 对其进行测试时,它运行良好。 谢谢@AQEEL AHMED,我的问题是我在 didSelectPost 结束时调用了 completeRequestReturningItems,所以我的 loadItem 回调永远不会被调用,我认为这对于其他人来说可能是一个重要的点,比如我:)【参考方案2】:
- (void)loadItemForTypeIdentifier:(NSString *)typeIdentifier options:(nullable NSDictionary *)options completionHandler:(nullable NSItemProviderCompletionHandler)completionHandler;

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

item可能有多种类型。

【讨论】:

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

以上是关于如何在 iOS 共享扩展中获取屏幕截图?的主要内容,如果未能解决你的问题,请参考以下文章

没有在移动 ios 魅力报告中获取屏幕截图

共享 SwiftUI 视图的屏幕截图导致崩溃

如何以编程方式截取可扩展的uitableview的屏幕截图

IOS iMessage扩展截图检测

如何在 SDL 2 中获取并保存 BMP 屏幕截图?

如何使用 React-Native 在 iOS 中禁用屏幕截图