在 iOS 中使用共享扩展程序从邮件应用程序共享附件

Share attachment from Mail App with Share extension in iOS

现在我正在开发应用程序,该应用程序应该实现共享扩展以从邮件应用程序共享附件。它应该支持不同的文件扩展名(几乎所有类型的文件)。从 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>

提前致谢。

所以我终于找到了问题的答案!以防万一有人遇到同样的问题.. 首先,我必须在 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

祝动作扩展开发顺利!欢迎提问!