Search code examples
swiftemailemail-attachmentsios-app-extensionuti

Open attachment from mail using ios 8 app [swift]


In my app, I designed a new encrypted type data as attachment to the mail. When I receive the same type of attachment(filename.filetype) from another user, I want the attachment from mail to open in my app. I went through the action extensions tutorials. But, what is missing is, how can I open that particular type of attachment using my swift app. I get the answers in Obj-C as well as the previous versions of iOS. I am seeking an answer in iOS8, Swift to handle the file.

Here is my info.plist

<key>UTExportedTypeDeclarations</key>
<array>
    <dict>
        <key>UTTypeConformsTo</key>
        <array>
            <string>public.data</string>
        </array>
        <key>UTTypeDescription</key>
        <string>pvt file</string>
        <key>UTTypeIdentifier</key>
        <string>com.pryvateBeta.pvt</string>
        <key>UTTypeTagSpecification</key>
        <dict>
            <key>public.filename-extension</key>
            <string>pvt</string>
        </dict>
    </dict>
</array>
<key>CFBundleDocumentsType</key>
<array>
    <dict>
        <key>CFBundleTypeIconFiles</key>
        <array/>
        <key>CFBundleTypeName</key>
        <string>pvt file</string>
        <key>CFBundleTypeRole</key>
        <string>Viewer</string>
        <key>LSHandlerRank</key>
        <string>Owner</string>
        <key>LSItemContentTypes</key>
        <array>
            <string>com.pryvateBeta.pvt</string>
        </array>
    </dict>
</array>

Here is my AppDelegate

func application(application: UIApplication, openURL Url: NSURL, sourceApplication: String?, annotation: AnyObject?) -> Bool {
    let encrypteddata = NSData(contentsOfURL: Url)

    return true}

Solution

  • First of all you need to declare the file type your app will handle in your apps Info.plist.

    For instance the configuration shown below declares that the app is able to open .lumenconfig files which are basically XML. See this for more info about the declarations.

    <key>CFBundleDocumentTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeName</key>
            <!-- The name of this file type. -->
            <string>Lumen Configuration</string>
            <key>CFBundleTypeIconFiles</key>
            <!-- The name of this file type. -->
            <array/>
            <key>LSItemContentTypes</key>
            <!-- The different type identifiers that are handled 
                 as this type of file. -->
            <array>
                <!-- This is a custom type I declare below -->
                <string>at.zujab.lumen.lumenconfig</string>
            </array>
        </dict>
    </array>
    

    If you use a custom type like I do in the above example you also need to declare that type. See this for more information about declaring your own type

    <key>UTExportedTypeDeclarations</key>
    <array>
        <dict>
            <key>UTTypeConformsTo</key>
            <!-- How these files are structured -->
            <array>
                <string>public.xml</string>
            </array>
            <key>UTTypeIdentifier</key>
            <!-- This is the identifier for the custom type -->
            <string>at.zujab.lumen.lumenconfig</string> 
            <key>UTTypeDescription</key>
            <!-- How your app calls these files. -->
            <string>Lumen Configuration File</string>
            <key>UTTypeTagSpecification</key>
            <dict>
                <key>public.filename-extension</key>
                 <!-- The extension of the files of this type -->
                <string>lumenconfig</string>
            </dict>
        </dict>
    </array>
    

    Then in your app delegate implement a handler to handle the file:

    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
    
        //....
    
        func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject?) -> Bool {
            //url contains a URL to the file your app shall open
    
            //In my EXAMPLE I would want to read the file as a dictionary
            let dictionary = NSDictionary(contentsOfURL: url)
    
        }
    
    }