Universal Links

192 Views Asked by At

I'm trying to implement Universal links I'm able to launch the app but stuck in routing. How to decode ids and bind them with viewcontrollers. Link looks like this.

https://myapp.com/#/observation/c2hhcmlhcl9pY29udHJvbGFwcF9zZV9faXJlcG9ydGxpdGVfdG9rZW4/project_1496669822_ea024600-3b13-4565-bc1e-b5892c521121/party_1496669822_618ecdd4-5649-4ebd-a43f-46fa64b56732/inspection_test_8853A89C-2F66-4B10-9DD4-2B248D4010F7/defect_2017-08-31_16_53_test_15041912125876/%22

Here is how looks my code

class DeeplinkParser {

    static let shared = DeeplinkParser()
    private init(){}

    func parseDeepLink(_ url: URL) -> DeeplinkType? {

        guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true), let host = components.host else {
            return nil
        }

        var token = components.user?.components(separatedBy: "/")
        var pathComponents = components.path.components(separatedBy: "/")
        var linkFragment = components.fragment?.components(separatedBy: "/")
        let queryItems = components.queryItems
        //var pathComponents = url.pathComponents

        pathComponents.removeFirst()

        switch host {
            case "app.icontrolapp.se":
                let projectIdString = pathComponents.filter({ $0.hasPrefix("project_")}).first
                if let projectId = projectIdString?.components(separatedBy: "_").last {
                    findSession(components: components)

                    if let urlPath = parseDeepLink(url) {
                        //print("Url Path: \(urlPath)")
                        let proj = URLSession.shared.dataTask(with: url) {(data, response, error) in
                            if error != nil {
                                print("Error\(error)")
                            } else {
                                if let usableData = data {
                                    print(usableData)
                                }
                            }
                        }
                        proj.resume()
                    }

                    print("Path Components 0: \(pathComponents[0])")
                    print("Path Components 1: \(pathComponents[1])")
                    print("Path Components 2: \(pathComponents[2])")
                    print("Path Components 3: \(pathComponents[3])")

                    print("ProjectId: \(projectId)")
                    print(findSession(components: components))

                    return DeeplinkType.projects(.details(id: projectId))
                }
            case "closeout.icontrolapp.se":
                guard var tokenId = linkFragment?[2], let projetId = linkFragment?[3], let teamId = linkFragment?[4], let inspectionId = linkFragment?[5], let issueId = linkFragment?[6] else { return nil }

                //guard let userId = linkFragment?[2], let teamId = linkFragment?[4], let inspectionId = linkFragment?[5], let issueId = linkFragment?[6] else { return nil }

                print("Token ID \(tokenId)")
                print("Project ID \(projetId)")
                print("Team ID  \(teamId)")
                print("Inspection ID \(inspectionId)")
                print("Issue ID \(issueId)")
 let session = Session.currentSession()
                session?.userID?.append(tokenId)

                tokenId.append((session?.userID)!)

                let project = ProjectEntity.get(projetId)
                let report = Report.get(inspectionId)

                print("Report: \(report!)")

                let issue = Issue.get(issueId)

                session?.selectProject(project)
                session?.selectReport(report)

                //session?.selectReport(report)
                CurrentIssue.sharedInstance.makeIssueCurrentSelection(issue!, db: CBLDatabase.db()!)

                let appDelegate = UIApplication.shared.delegate as! AppDelegate
                let window = appDelegate.window!
                return DeeplinkType.observation(tokenId: tokenId, projectId: projetId, teamId: teamId, issueId: issueId, inspectionId: inspectionId)
        default:
            break
        }
        return nil
    }

}


import UIKit

enum DeeplinkType{
    enum Projects {
        case root
        case details(id: String)
    }

    case projects(Projects)
    case projectId(Projects)
    case observation(tokenId: String, projectId: String, teamId: String, issueId: String, inspectionId: String)
    case teamId
    case request(id: String)
}


enum Route {
    case issue
    case bluePrint

    init?(url: URL) {
        switch url.absoluteString {
        case "\(url)//defect_2017-08-31_16_53_test_15041912125876": self = .issue
        default: return nil
        }
    }
}

var Deeplinker = DeepLinkManager()
class DeepLinkManager{

    fileprivate init(){}

    private var deeplinkType: DeeplinkType?


    func handleRoute(route: Route) {
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        let window = appDelegate.window!

        let issueVC = window.rootViewController as! IssuesViewController

        switch route {
        case .issue: issueVC.showMenu()
        default: brea
        }
    }

    @discardableResult
    func handleDeeplink(url: URL) -> Bool {
        deeplinkType = DeeplinkParser.shared.parseDeepLink(url)
        return deeplinkType != nil
    }

    func checkDeepLink() {
        guard let deeplinkType = deeplinkType else {
            return
        }

        DeeplinkNavigator.shared.proceedToDeeplink(deeplinkType)

        self.deeplinkType = nil
    }
}

class DeeplinkNavigator: UIViewController {

    static let shared = DeeplinkNavigator()
    //private init() {}

    var window: UIWindow?

    private var alertController = UIAlertController()

    func proceedToDeeplink(_ type: DeeplinkType) {
        switch type {
        case .observation(let tokenId, let projectId, let teamId, let issueId, let photoId):
            presentView()
        case .projects(.root):
            displayAlert(title: "Project Root")
        case .projects(.details(id: let id)):
            displayAlert(title: "Project Details bla bla bla \(id)")
        case .request(id: let id):
            displayAlert(title: "Request Details \(id)")
        /*case .project(id: let id):
            displayAlert(title: "project details \(id)")*/
        default: break
        }
    }

    private func displayAlert(title: String) {
        alertController = UIAlertController(title: nil, message: nil, preferredStyle: .alert)
        let okButton = UIAlertAction(title: "Ok", style: .default, handler: nil)
        alertController.addAction(okButton)
        alertController.title = title
        if let vc = UIApplication.shared.keyWindow?.rootViewController{
            if vc.presentedViewController != nil {
                alertController.dismiss(animated: false, completion: { 
                    vc.present(self.alertController, animated: true, completion: nil)
                })
            } else {
                vc.present(alertController, animated: true, completion: nil)
            }
        }
    }
1

There are 1 best solutions below

0
On

My personal experience has shown that this is not FE responsibility. One possible scenario is after receiving the URL to send it to the BackEnd and from that point you should receive deeplink or error for translation. Also, your app should navigate through screens with deeplinks.