Programming/iOS

[iOS/Swift5] Universal Links 예제 프로젝트

devssun 2020. 4. 16. 22:22
728x90
반응형

Universal Links (iOS13)

예제 프로젝트 링크

1. Web과 App에 Universal Link 활성화하기

  1. 우선 해당 기능을 테스트 해보기 위해선 웹 사이트와 애플 개발자 계정이 필요하다.
  2. App 프로젝트를 만든 뒤 Associated Domain을 추가한다.
    • applinks:naver.com 형식으로 값을 추가한다.
  3. 아래와 같은 포맷으로 apple-app-site-association 파일을 만든 뒤 웹 사이트의 루트에 추가한다. (해당 파일은 json 포맷이지만 확장자없이 저장해야 한다.)
    • apps : Universal Link에서는 사용하지 않으나 꼭 필요한 포맷이므로 빈 배열로 정의한다.
    • appID : 애플 개발자 계정을 생성하면 Team ID가 만들어지는 데 해당 ID는 developer.apple.com 에서 확인 가능하다. Bundle ID는 프로젝트 Target 들어가서 확인 가능하다. (<> 는 빼야 한다.)
    • path : paths의 값은 특정 폴더나 파일명으로 지정할 수 있습니다.
        {
            "applinks": {
                "apps": [],
                "details": [{
                    "appID": "<TeamID>.<BundleID>",
                    "paths": ["*"]
                    }
                }]
            }
        }

2. App에서 Universal Link 핸들링하기

  • 유니버설 링크는 앱 실행 → 링크 수신 → 콘텐츠 표시으로 동작하게 된다. 앱이 실행되고 링크가 수신되면 아래 메소드가 호출된다. (나는 분명 AppDelegate에 메소드를 구현했는데 계속 호출이 안되서 고민하다가.. 프로젝트 최소 버전이 iOS 13이었고 UIScene이 생각났다. )
  1. iOS 12 이하 (AppDelegate.swift 에 구현)

         func application(_ application: UIApplication,
                          continue userActivity: UIUserActivity,
                          restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool
         {
             // Get URL components from the incoming user activity
             guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
                 let incomingURL = userActivity.webpageURL,
                 let components = NSURLComponents(url: incomingURL, resolvingAgainstBaseURL: true) else {
                 return false
             }
    
             // Check for specific URL components that you need
             guard let path = components.path,
             let params = components.queryItems else {
                 return false
             }    
             print("path = \(path)")
    
             if let albumName = params.first(where: { $0.name == "albumname" } )?.value,
                 let photoIndex = params.first(where: { $0.name == "index" })?.value {
    
                 print("album = \(albumName)")
                 print("photoIndex = \(photoIndex)")
                 return true
    
             } else {
                 print("Either album name or photo index missing")
                 return false
             }
         }
  2. iOS 13 이상 (SceneDelegate.swift 에 구현)

         func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
                 print("SceneDelegate - continue userActivity")
                 guard userActivity.activityType == NSUserActivityTypeBrowsingWeb, let url = userActivity.webpageURL else {
                         return
                 }
    
                 print("url : \(url)")
    
                 if let components = URLComponents(url: url, resolvingAgainstBaseURL: true) {
                     let path = components.path
                     print("path : \(path)")
                 }
    
                 guard let rootViewController = self.window?.rootViewController else {
                     return
                 }
    
                 guard let viewController = rootViewController as? ViewController else {
                     return
                 }
    
                 viewController.URLLabel.text = url.absoluteString
             }

이렇게 해서 링크를 클릭했을 때 앱이 실행되고, 사파리로 URL을 접속하면 상단에 앱 열기가 보이는 것을 확인할 수 있다.


궁금한 점

  • 웹에서 앱을 한번 실행하면 다음부턴 앱이 바로 실행되야 할 것 같은데 안된다.
  • Team ID가 외부에 공개되도 괜찮은가? (깃헙 같은 플랫폼)
    • 나중에 확인해보니 이미 다른 프로젝트에서도 다 깃헙에 올라가고 있었음. 쓸데없는 고민

번외

  • 블로그 글은 노션에서 작성 후 블로그로 옮기고 있는데 티스토리에서 마크다운이 제대로 안되 얼마전 github 포맷으로 적용함 근데 깃헙 포맷으로 하니 대시, 점 같은 게 제대로 표기가 안됌.... 그래서 또 복구했다 ㅠ
반응형