Handling Universal Links in your app

With all parts in place you can now adapt your app to Universal Links. In the previous chapter, we did a lot of work to handle continuing user activities. The implementation that is shown uses the application(_:continue:restorationHandler:) method to inspect and dissect user activities and it serves as a handoff point for us to call other methods from. This setup now becomes very beneficial because we could use a similar setup to handle Universal Links.

Whenever our application is expected to open a Universal Link, the application(_:open:options:) method is called on the AppDelegate. This method receives the URL it's expected to open. If we're not able to open the URL for whatever reason, this method is expected to return false. If this method does manage to handle the URL, it's expected to return true.

Any application that handles Universal Links is expected to have the Associated Domains capability set up. To do this, go to the Capabilities tab in your project settings and enable Associated Domains. For every domain that you want to handle Universal Links for, you need to create a new applinks: entry. The following screenshot shows an example implementation:

Handling Universal Links in your app

We've already established that our application receives a URL and that we're supposed to handle opening it. In other words, we need to map the URL we receive to a view in our application and take the user to that specific view. This process is called routing and it's a well-known technique throughout programming languages and platforms.

Let's assume that our application received the following URL:

https://www.familymoviesapp.com/familymember/dylan/ 

Just by looking at this URL you probably have a vague idea of what should happen if an application is asked to open this URL. We should be taken to a family member screen that shows the detail page for Dylan.

Whenever we're passed a URL like this in AppDelegate, there are three properties of the URL that we can distinguish. One is the scheme; this property tells us which URL scheme, for example, https:// was used to navigate to the app. Usually the scheme isn't very relevant to your app unless you're handling multiple custom URL schemes. Second, there is the host, e.g.  example.com. This property describes the domain that belongs to the URL. Again, usually not relevant unless your app handles links from multiple hosts. Finally, there is the pathComponents property. The pathComponents is an array of components that are found in the path for the URL. Printing the pathComponents for the example URL gives the following output:

["/", "familymember", "dylan"] 

The first component can be ignored, usually because it's just a /. The second and third components are a lot more interesting. They tell you more about the route that we need to resolve. Going back to the FamilyMovies example, we could handle URLs in that app easily with the methods present in AppDelegate. Let's see how:

func application(_ app: UIApplication, open URL: URL, options: 
  [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool { 
    let pathComponents = URL.pathComponents 
    guard pathComponents.count == 3 
        else { return false } 
     
    switch(pathComponents[1], pathComponents[2]) { 
    case ("familymember", let name): 
        return handleOpenFamilyMemberDetail(withName: name) 
    case ("movie", let name): 
        return handleOpenMovieDetail(withName: name) 
    default: 
        return false 
    } 
} 

We're using a switch with powerful pattern matching to check whether the second component in the URL points to a family member or a movie and we parse the third component into a variable called name. If one of these matches, we call the existing methods and if nothing matches, we return false to indicate the fact that we couldn't open the URL.

Earlier, you saw this URL: https://www.donnysrecipes.com/search/?q=macaroni. With pathComponents you can easily gain access to the search portion of the URL. But how do you get the final part of the URL? Well, that's a little harder. We can get the query property for a URL but then we get a single string in the form of q=macaroni. What we really want is a dictionary with q as a key and macaroni as a value. The following extension on URL implements a naive method to make this happen:

extension URL { 
    var queryDict: [String: String]? { 
        guard let pairs = query?.components(separatedBy: "&") 
            else { return nil } 
         
        var dict = [String: String]() 
         
        for pair in pairs { 
            let components = pair.components(separatedBy: "=") 
            dict[components[0]] = components[1] 
        } 
         
        return dict 
    } 
} 

First, we obtain the query string. Then we separate the string by the & character because multiple key value pairs in the query string are expected to be separated with that character. We loop over the resulting array and we separate each string on the = character. The first item in the resulting array is expected to be the key and the second is the value. We add each key and value to a dictionary and finally that dictionary is returned. This enables us to get the value for q as shown below:

URL.queryDict!["q"] 

Armed with this information you're ready to add URL handling to your applications in a flexible way. Let's see how Universal Links can help straighten out the login experience for your users.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.192.3