Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ディープリンクの
設計と実装 - iOSDC2017

ninjinkun
September 16, 2017

ディープリンクの
設計と実装 - iOSDC2017

一休レストランiOSアプリでディープリンクを実装する際に得られた知見を共有します

ninjinkun

September 16, 2017
Tweet

More Decks by ninjinkun

Other Decks in Programming

Transcript

  1. 63-εΩʔϜ w ͖ͬ͞ͷόφʔ͔Β։͘ํ w ಠࣗͷ63-εΩʔϜΛఆٛ͢Δ w ྫ w υϝΠϯΛೖΕ͍ͯΔཧ༝͸ޙड़ w

    J1IPOF04 ೥ ͔Βར ༻Մೳ σΟʔϓϦϯΫͱ͸ʁ rsikyu://restaurant.ikyu.com/100198/
  2. 63-εΩʔϜ w ଞࣾΞϓϦ͔Β։͘ʹ͸ಠࣗ63-εΩʔϜΛ૊Έࠐ ΜͰ΋Β͏ඞཁ͕͋Δ w εΩʔϜΛ֤ΞϓϦʹϋʔυίʔσΟϯά͢Δඞཁ ͕͋Δ σΟʔϓϦϯΫͱ͸ʁ let IkyuScheme

    = "rsikyu" let IkyuDomain = "restaurant.ikyu.com" func openIkyuRestaurant(restaurantId: Int) { UIApplication.shared.open( URL(string: "\(IkyuScheme)://\(IkyuDomain)/\(restaurantId)/")!, options: [ : ], completionHandler: nil ) }
  3. 6OJWFSTBM-JOLT w ͖ͬ͞ͷ(PPHMF͔Β։͘ํ w )551 4 ͷ63-͔ΒΞϓϦΛ ։͘ w ྫ

    w J04 ೥ ͔Βར༻Մೳ σΟʔϓϦϯΫͱ͸ʁ https://restaurant.ikyu.com/100198/
  4. ࣮૷ w ۪௚ʹ"QQ%FMFHBUFΛ࣮૷͢Δͱ෼ذͩΒ͚ʹ 63-εΩʔϜઃܭͱ࣮૷ func application(_ app: UIApplication, open url:

    URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool { guard let scheme = url.scheme else { return false } switch scheme { case "rsikyu": switch url.path { case "/reserve": return true case "/login": return true default: return false } default: return false } }
  5. 63-ϧʔλʔ࢖͏ͱָ w 63-ͷύʔεͱը໘ͷݺͼग़͠͸ϧʔλʔʹ೚ͤΔ w ΫΤϦͷύʔεͱ͔஍ຯʹ໘౗ w ҰٳͰ͸%FFQ-JOL,JUΛ࠾༻ 63-εΩʔϜઃܭͱ࣮૷ func application(_

    app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool { return Router().handle(url, withCompletion: nil) } router["/:restaurant_id([0-9]{6})"] = { (deepLink: DPLDeepLink?) in ... } pathఆٛ ݺͼग़͠
  6. IPTUΛೖΕΔϝϦοτ w "OESPJEͱڞ௨Խ͢Δͷָ͕ w "OESPJEͰ͸IPTUͱQBUIΛ۠ผͯ͠ઃఆ͢Δ w "OESPJEΤϯδχΞ͕ී௨ʹ63-ઃܭ͢Δͱɺύε Ͱը໘෼ذ͢ΔΑ͏ʹ࡞Δʢͱࢥ͏ʣ 63-εΩʔϜ͝ఏҊ Android

    Manifest.xml <intent-filter> … <data android:scheme=“rsikyu" android:host="restaurant.ikyu.com" android:pathPrefix=“/search" /> </intent-filter>
  7. BQQMFBQQTJUFBTTPDJBUJPOϑΝΠϧ w αΠτͷτοϓ௚Լʹஔ͘ 6OJWFSTBM-JOLTઃܭͱ࣮૷ https://restaurant.ikyu.com/apple-app-site-association { "applinks": { "app": [],

    "details": [ { "appID": "53M4W6LWLM.com.ikyu.restaurant", "paths": [ "NOT /rsCosite.asp", "NOT /mdr.asp", "/rsSd/1?????/amp/", "/rsSd/1?????/amp/*", "/1?????/plan????????/", "/1?????/", "/rsSd/main/script/restU.asp", "/rsSd/main/script/planU.asp", "/rsSd/", "/" ] } ] } } ͙͙Ε͹ग़ͯ͘ΔͷͰख୹ʹ…
  8. BQQMFBQQTJUFBTTPDJBUJPOϑΝΠϧ w ଞࣾͷϑΝΠϧΛࢀߟʹ͢Δ w ΈΜͳΞΫηεՄೳͳͱ͜Ζʹஔ͍͍ͯΔͷͰ 6OJWFSTBM-JOLTઃܭͱ࣮૷ https://instagram.com/apple-app-site-association { "webcredentials": {

    "apps": [ "777W53UFB2.com.burbn.instagram", "MH9GU9K5PX.com.burbn.instagram", "T84QZS65DQID.com.facebook.Instagram", "3NW3KR6Q88.com.facebook.Instagram", "3NW3KR6Q88.com.facebook.InstagramInHouse" ] }, "applinks": { "apps": [], "details": [ { "appID": "777W53UFB2.com.burbn.instagram", "paths": [ "NOT /about/*", "NOT /about", "NOT /developer/*", "NOT /developer",
  9. "QQ%FMFHBUF w 63-εΩʔϜ͕࣮૷ࡁΈͩͱָ 6OJWFSTBM-JOLTઃܭͱ࣮૷ func application(_ application: UIApplication, continue userActivity:

    NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool { if userActivity.activityType == NSUserActivityTypeBrowsingWeb { if let webpageURL = userActivity.webpageURL { // URLεΩʔϜʹม׵ͯ͠ىಈ let urlScheme = URLSchemeConverter.convertUniversalLinks(url: webpageURL) return Router().handle(url: urlScheme) } } return false }
  10. 63-εΩʔϜʹม׵͢Δॲཧ 6OJWFSTBM-JOLTઃܭͱ࣮૷ static func convertUniversalLinks(url: URL) -> URL { let

    baseURL = "rsikyu://restaurant.ikyu.com/" let query = url.query ?? "" let restaurantId = url.queryStrings["rstId"] ?? "" let planNo = url.queryStrings["planNo"] ?? "" switch url.path { case “/rsSd/main/script/restU.asp”: // URLεΩʔϜͱpath͕Ұக͍ͯ͠ͳ͍΋ͷ͸खಈม׵ return URL(string: "\(baseURL)\(restaurantId)?\(query)") ?? url case "/rsSd/main/script/planU.asp": return URL(string: "\(baseURL)\(restaurantId)/plan\(planNo)") ?? url case "/rsSd/": return URL(string: "\(baseURL)") ?? url case "/rsMain/rsSrchPlan.asp", "/rsSd/main/script/srchLstU.asp", "/rsSd/main/script/srchRestLstU.asp": return URL(string: "\(baseURL)search?\(query)") ?? url case nil: return URL(string: "\(baseURL)")! default: return URL(string: "\(baseURL)\(url.path)") ?? url } }
  11. SFGFSSFS͕ͳ͍ dJ04 w ΞϓϦଆͰ͸ݩ63-͔͠Θ͔Βͳ͔ͬͨ w ఏܞαΠτ͔Βͷίϯόʔδϣϯ͕ܭଌͰ͖ͳ͍ w J04Ͱ͸ղܾ 6OJWFSTBM-JOLT͓೰ΈϙΠϯτ /*

    The URL of the webpage that referred (linked to) webpageURL.*/ @available(iOS 11.0, *) open var referrerURL: URL?
  12. ".1ͱͷ݉Ͷ߹͍ w (PPHMFͷݕࡧ݁Ռ͔Β͸·ͣ".1 ͕։͘ w ".1Ωϟογϡ͸(PPHMFʹϗε ςΟϯά͞Ε͍ͯΔ w 6OJWFSTBM-JOLT͕ൃಈ͠ͳ͍ w

    (PPHMFˠ".1ˠΞϓϦͱ͍͏ભ ҠʹͳΔ w ͪͳΈʹ".1ͷJGSBNF಺ͷϦϯΫ͕6OJWFSTBM -JOLTͰ։͚Δͷ͸J04͔Β 6OJWFSTBM-JOLT͓೰ΈϙΠϯτ