paint-brush
EmailPresenter.swiftby@harrybloom18
5,560 reads
5,560 reads

EmailPresenter.swift

by Harry BloomMarch 23rd, 2017
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

We needed to display an list of help options to the user in multiple places in our app. <a href="https://hackernoon.com/tagged/monzo" target="_blank">Monzo</a> and <a href="https://hackernoon.com/tagged/slack" target="_blank">Slack</a> have handled this well in the past with producing an action sheet of installed email clients.

Companies Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - EmailPresenter.swift
Harry Bloom HackerNoon profile picture

Deep link to your installed email clients

We needed to display an list of help options to the user in multiple places in our app. Monzo and Slack have handled this well in the past with producing an action sheet of installed email clients.

Here we are going to create a similar action sheet, which will show the users installed email clients on the phone, and give them the ability to open them from our app.

For this we will need to do a few things, and I will walk you through the steps I took one by one.

Find the code here, along with a simple sample project.

Create the UI component

At WeVat, we are trying to ‘componentise’ the application where ever we can, through the use of protocols. Shout out to Matthijs Hollemans and Natasha The Robot for their insightful articles on this subject.

This part of functionality will be well suited into a ‘Presenter’ type component. I will show you how we achieve this:

Create the Presenter protocol:

Here we:

1) Define the UIAlertController we will be using for the action sheet

2) Define the setup function which will configure the action sheet. This will later be called from viewDidLoad

Setup the action sheet

In an extension on our protocol, we define the setup that is needed for the action sheet. Currently we will just setup the static elements, which is the title and the cancel button.

Conform to the protocol in our view controller

So now we have successfully setup the action sheet in a presenter class, ready to be shown from whichever view controller wants!

Run the app and you should see an action sheet appear like this

Empty Action Sheet

Get a list of installed email clients

To open another app on your device in iOS, you need to use iOS URL schemes. I will again break this into the below steps for clarity:

Locate the URL scheme for the required apps

Maybe my googling skills are not upto scratch, but this was the most time consuming part of the process. After searching the depths of the internet, I came across this reddit post which outlined lists of URL schemes for iOS apps (thank you /user/meefmaster!).

We have decided to include the following email clients so far: Mail, Dispatch, Outlook, Gmail and Inbox.

Identify which apps the user has installed

There is an instance method on UIApplication which will test if the installed application can open a URL. This is perfect for our needs, so we can do this with the below code:

Create actions to open these apps

Now we can tell which of the email clients the user has installed on their device, we can go ahead and wire them into the action sheet actions!

1) Create UIAlertAction

We can now create a safe method to create UIAlertActions to open the email apps the user has installed

Note the warning for users targeting only iOS 10 & above : https://useyourloaf.com/blog/openurl-deprecated-in-ios10/

Add our actions to our ActionSheet if they exist

Now try and run the app on your device (the iOS Simulator does not support openURL schemes for this). Boom! It doesn’t work. We need to first make sure of one more thing. You may see this message in your console:

-canOpenURL: failed for URL: “googlegmail:///” — error: “This app is not allowed to query for scheme googlegmail:///”

This is here because we need to explicitly tell our app which other apps we intend to access.

2) Add the the scheme to your info.plist

We can do this through the beautiful thing that is the Info.plist file. Add a new key called LSApplicationQueriesSchemes as an array. Then you can enter your apps within the array. The Mail app doesn’t need to go in here, presumably because it is an Apple app. Your entry should look like the below.

Info.plist

If you are still seeing the message, ensure you actually have the app installed on your device 😉

Run and voila! You should see the actionsheet appear like below:

Tap on an action and it should open the corresponding email application.

Give it some context!

Upon tapping on a mail option, you will discover that it will open the email client. In our use case, this was tapped when the user wants to email our help address, therefore the subject and recipient will always be the same. As you might have noticed if you saw some of the iOS URL Schemes, you can pass query parameters in the app through the link.

We want to pass these in when we build the Alert Actions, so I have refactored this out to do so, each email in their own functions.

One last thing we will need to do is URL encode the subject line before we pass it into the URL. We can do this by calling subjectString?.addingPercentEncoding(withAllowedCharacters:NSCharacterSet.urlQueryAllowed) on the string.

Last last thing…

There is always the possibility to one of our users doesn’t have one of the listed apps installed, or indeed just accesses their emails through a web browser. In this case, we can simply give them the option of opening in Safari.

We can refactor our code slightly to make this work by populating our Alert Actions into a temporary array, and then populate our ActionSheet with Safari only if this array is empty.

And refactor our setup function to look like this:

Wrap up

So we’re pretty much done here. You will now be able to reuse this logic whenever you want to add email options to your users. Just conform to your new presenter protocol!

If you wanted to reuse this presenting logic, for different types of apps than email, then you just need to find the URL schemes you need and repeat the process. Simple!

Thanks for reading this far. Please do comment if you have any thoughts around this area, or think it could be improved!