Opening URLs Safely - Security - iOS 9 Swift Programming Cookbook (2015)

iOS 9 Swift Programming Cookbook (2015)

Chapter 11. Security

11.3 Opening URLs Safely

Problem

You want to find out whether an app on the user’s device can open a specific URL.

Solution

Follow these steps:

1. Define the key of LSApplicationQueriesSchemes in your plist file as an array.

2. Under that array, define your URL schemes as strings. These are the URL schemes that you want your app to be able to open.

3. In your app, issue the canOpenUrl(_:) method on your shared app.

4. If you can open the URL, proceed to open it using the openUrl(_:) method of the shared app.

5. If you cannot open the URL, offer an alternative to your user if possible.

Discussion

In iOS, previously, apps could issue the canOpenUrl(_:) call to find out whether a URL could be opened on the device by another application. For instance, I could find out whether I can open “instagram://app” (see iPhone Hooks : Instagram Documentation). If that’s possible, I would know that Instagram is installed on the user’s device. This technique was used by some apps to find which other apps are installed on the user’s device. This information was then used for marketing, among other things.

In iOS 9, you need to use the plist file to define the URLs that you want to be able to open or to check whether URLs can be opened. If you define too many APIs or unrelated APIs, your app might get rejected. If you try to open a URL that you have not defined in the plist, you will get a failure. You can use canOpenUrl(_:) to check whether you can access a URL before trying to open it: the method returns true if you have indicated that you can open that kind of URL, and false otherwise.

Let’s check out an example. I’ll try to find first whether I can open the Instagram app on the user’s device:

guard let url = NSURL(string: "instagram://app") where

UIApplication.sharedApplication().canOpenURL(url) else{

return

}

Now that I know I can open the URL, I’ll proceed to do so:

guard UIApplication.sharedApplication().openURL(url) else{

print("Could not open Instagram")

return

}

print("Successfully opened Instagram")

I’ll then go into the plist file and tell iOS that I want to open URL schemes starting with “instagram”:

<plist version="1.0">

<array>

<string>instagram</string>

</array>

</plist>

See Also