使用 iOS 中的共享扩展从 Mail App 共享附件

Posted

技术标签:

【中文标题】使用 iOS 中的共享扩展从 Mail App 共享附件【英文标题】:Share attachment from Mail App with Share extension in iOS 【发布时间】:2016-04-08 10:02:13 【问题描述】:

现在我正在开发应该实现共享扩展以从邮件应用程序共享附件的应用程序。它应该支持不同的文件扩展名(几乎所有类型的文档)。从 Apple 文档中,我了解到我必须在 Info.plist 中使用 Predicate,但在 SO 的答案中,我发现我必须在代码中使用它。现在我被困在了这一点上,无法继续前进。这是我想从 post 中使用的谓词。

SUBQUERY (
            extensionItems,
            $extensionItem,
            SUBQUERY (
            $extensionItem.attachments,
            $attachment,

            (
                       ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "com.adobe.pdf"
                    || ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.image"
                    || ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.png"
                    || ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.jpeg"
                    || ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.jpeg-2000"
                    || ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.tiff"
                    || ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "com.compuserve.gif"
                    || ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "com.microsoft.bmp"
                    || ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "com.microsoft.word.doc"
                    || ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "org.openxmlformats.wordprocessingml.document"
            )
).@count == $extensionItem.attachments.@count
).@count == 1

谁能建议如何在我的 swift 代码中使用这个谓词:

    for attachment in content.attachments as! [NSItemProvider] 
        if attachment.hasItemConformingToTypeIdentifier(contentType) 

            attachment.loadItemForTypeIdentifier(contentType, options: nil)  data, error in
                if error == nil 
                    let url = data as! NSURL
                    if let fileData = NSData(contentsOfURL: url) 
                        self.selectedFile = NSData(data: fileData)
                    
                 else 

                    let alert = UIAlertController(title: "Error", message: "Error loading file", preferredStyle: .Alert)

                    let action = UIAlertAction(title: "Error", style: .Cancel)  _ in
                        self.dismissViewControllerAnimated(true, completion: nil)
                    

                    alert.addAction(action)
                    self.presentViewController(alert, animated: true, completion: nil)
                
            
        
    

这是我的 NSExtensionActivationRule:

        <key>NSExtensionActivationRule</key>
        <dict>
            <key>NSExtensionActivationSupportsAttachmentsWithMaxCount</key>
            <integer>1</integer>
        </dict>

提前致谢。

【问题讨论】:

【参考方案1】:

所以我终于找到了我的问题的答案!以防万一有人遇到同样的问题.. 首先,我必须在 Info.plist 中使用 PREDICATE 语句(子查询)而不是键 NSExtensionActivationSupportsAttachmentsWithMaxCount。喜欢:

        <key>NSExtensionActivationRule</key>
        <string>SUBQUERY (
            extensionItems,
            $extensionItem,
            SUBQUERY (
            $extensionItem.attachments,
            $attachment,
            (
            ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "com.adobe.pdf"
            || ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.image"
            || ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.plain-text"
            || ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.png"
            || ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.jpeg"
            || ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.jpeg-2000"
            || ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.tiff"
            || ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "com.compuserve.gif"
            || ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "com.microsoft.bmp"
            || ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "com.microsoft.word.doc"
            )
            ).@count == 1   // Important! to activate extension only on 1 chosen image
            ).@count == 1
        </string>

第二:使用必要的TypeIdentifier(UTI)正确获取所有附件:

    if let content = extensionContext!.inputItems.first as? NSExtensionItem 
        if let contents = content.attachments as? [NSItemProvider] 
            for attachment in contents
                attachment.loadItemForTypeIdentifier("public.item", options: nil)  data, error in
                    let url = data as! NSURL
                    let fileExtension = url.pathExtension as String!
                    let fileName = self.generateImageName() as String
                    if let fileData = NSData(contentsOfURL: url) 
                        self.uploadFile("\(fileName).\(fileExtension)", data: fileData)
                    
                
            
        
    

"public.item" - 是通用的 UTI,支持 NSExtensionActivationRule 字符串中列出的所有类型的文件扩展名。 你可以在https://developer.apple.com获得必要的UTI

祝你好运,开发动作扩展!欢迎提出任何问题!

【讨论】:

generateImageName() 怎么样,你能解释一下这个函数是做什么的吗?? 这是我的功能,它只是从所选文件的路径中获取原始文件名。

以上是关于使用 iOS 中的共享扩展从 Mail App 共享附件的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Xamarin.iOS 中的 iOS 扩展调用 NSUserDefaults Observer

从 iOS 容器应用与应用扩展共享 Firebase 身份验证会话

在 iOS8 中的 App 和 Extension 之间共享 Core Data 堆栈和数据

ActivityViewController 无法在 WhatsApp 和 Mail App 上共享链接?

自动滚动 UIScrollView 以适应原生 iOS Mail.app 中的内容

无法从共享扩展 ios 保存视频