动态 link 网页 URL 查询项在 Swift iOS 中为空

Dynamic link web URL query item is empty in Swift iOS

我正在从 QRCODE 扫描中深入link URL,但它显示 Web URL 查询为空(使用 firebase 动态 links 实现)。关联域设置为“applinks:avrhub.page.link/Product”.

info.plist 中的“FirebaseDynamicLinksCustomDomains”设置为“https://avrhub.page.link”和“https://avrhub.page.link/Product “

深link url:

深度代码linking:

func handleIncomingDynamicLink(_ dynamicLink:DynamicLink){
    
    
    
    guard let url = dynamicLink.url else {
            print("My Dynamic Link object has no url")
            return
        }
        print("Your Incoming link Parameter is \(url.absoluteString)")
        
        guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
        let queryItems = components.queryItems else {return}
        for queryItem in queryItems {
            
            Api.Params.inputProductId = Int(queryItem.value!)!
            print("Parameter \(queryItem.name) has a value of \(queryItem.value ?? "")")
        }
        
        Switcher.updateRootVC()
        Api.Params.isDeepLink = true

        if dynamicLink.matchType == .unique {
            print("The dynamic link is Unique")
        }
    }


func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
             
    if let incomingURL = userActivity.webpageURL {
        print("incoming URL is \(incomingURL)")
        let linkHandled = DynamicLinks.dynamicLinks().handleUniversalLink(incomingURL) { ( dynamicLink, error) in
            guard error == nil else {
                print("Found an error \(error!.localizedDescription)")
                return
            }
            if let dynamicLink = dynamicLink {
                self.handleIncomingDynamicLink(dynamicLink)
            }
            
        }
        if linkHandled {
  
            return true
        } else {
            return false
        }
    }
    
    return false
    
}


          
    func application(
        _ app: UIApplication,
        open url: URL,
        options: [UIApplication.OpenURLOptionsKey : Any] = [:]
    ) -> Bool {

        ApplicationDelegate.shared.application(
            app,
            open: url,
            sourceApplication: options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String,
            annotation: options[UIApplication.OpenURLOptionsKey.annotation]
        )
        
        
        
        if let dynamicLink = DynamicLinks.dynamicLinks().dynamicLink(fromCustomSchemeURL: url){
            self.handleIncomingDynamicLink(dynamicLink)
            return true
        } else {
            return GIDSignIn.sharedInstance().handle(url)
        }


    }

即使分析也没有给出任何错误

如评论中所述,您无法在 firebase 控制台中创建具有可变产品 ID 的动态 link,您需要随时生成它。如果需要,您还可以包括其他参数,这可能有助于分析,例如,如果您想知道哪个用户共享 link 及其影响...

我认为最好在 link 中添加产品 ID 作为查询参数。此外,它在多参数的情况下也会有所帮助。您可以使用参数名称轻松解析它,例如:

var productId: String?
let urlComponents = URLComponents(string: urlString)
if let queryItems = urlComponents?.queryItems {
    for queryItem in queryItems {
        if queryItem.name == "product_id" {
           productId = queryItem.value
        }
    }
}

这是我以编程方式生成动态 link 的代码。

func generateAndShareDynamicLink(event: Event, controller: UIViewController, presentationCompletion: @escaping (() -> Void), dismissCompletion: @escaping (() -> Void) ) {
        
        let user = Utility.shared.getCurrentUser()!
        let ownReferralCode = user.ownReferralCode.value
        let offerShareUrlString = youAPILink + "?referral=" + ownReferralCode + "&event_id=" + event.id.value + "&shared_by=" + user.userId.value + "&shared_by_name=" + user.fullName.value
        
        let url = URL(string: offerShareUrlString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!)!
        
        let iOSNavigationParams = DynamicLinkNavigationInfoParameters()
        iOSNavigationParams.isForcedRedirectEnabled = false
        
        let linkComponents = DynamicLinkComponents(link: url, domainURIPrefix: dynamicLinkGenaricDomain)!
        linkComponents.navigationInfoParameters = iOSNavigationParams
        linkComponents.iOSParameters = DynamicLinkIOSParameters(bundleID: bundleId)
        linkComponents.iOSParameters?.appStoreID = kAppStoreId
        linkComponents.iOSParameters?.customScheme = theBarCodeInviteScheme
        
        linkComponents.androidParameters = DynamicLinkAndroidParameters(packageName: androidPackageName)
        
        let descText = "\(user.fullName.value) has shared an event with you, check it out!"
        linkComponents.socialMetaTagParameters = DynamicLinkSocialMetaTagParameters()
        linkComponents.socialMetaTagParameters?.title = "App Name"
        linkComponents.socialMetaTagParameters?.descriptionText = descText
        linkComponents.socialMetaTagParameters?.imageURL = tbcLogoUrl
        
        linkComponents.otherPlatformParameters = DynamicLinkOtherPlatformParameters()
        linkComponents.otherPlatformParameters?.fallbackUrl = URL(string: barCodeDomainURLString)
        
        linkComponents.shorten { (shortUrl, warnings, error) in
            
            guard error == nil else {
                presentationCompletion()
                controller.showAlertController(title: "Share Event", msg: error!.localizedDescription)
                return
            }
            
            if let warnings = warnings {
                debugPrint("Dynamic link generation warnings: \(String(describing: warnings))")
            }
            
            let activityViewController = UIActivityViewController(activityItems: [descText, shortUrl!], applicationActivities: nil)
            activityViewController.popoverPresentationController?.sourceView = controller.view
            activityViewController.completionWithItemsHandler = { (activityType, completed:Bool, returnedItems:[Any]?, error: Error?) in
                dismissCompletion()
            }
            controller.present(activityViewController, animated: true, completion: {
                presentationCompletion()
            })
        }
        
    }

我同意另一个答案,解决这个问题的最好方法是让后端开发人员使用 Firebase Dynamic Links SDK 正确生成动态 link 并嵌入二维码中。

但是,如果您无法控制它,那么您可以获取传入的 link 并将其解析为嵌入的产品 ID。在这种情况下,您不需要使用某些动态 link 功能,例如,您可以改为执行以下操作:

if let incomingURL = userActivity.webpageURL {
    print("incoming URL is \(incomingURL)")
    handleIncomingURL(incomingURL)
}

//快速和肮脏的解析 - 你可以根据你的情况做一些更健壮的事情

func handleIncomingURL(_ url:URL) {
    
    guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true), let host = components.host else {
        return
    }
    var pathComponents = components.path.components(separatedBy: "/")
    // the first component is empty
    pathComponents.removeFirst()
    
    if pathComponents[0] == "Product" && pathComponents[1] != nil {
        print("found productId: \(pathComponents[1])")
        //Action here: jump to the right page from here, now that you have a product ID to work with
    } else {
        print("invalid URL path for my use case....")
    }
}

我遇到了同样的问题,因为在尝试从下面的函数

中获取 Firebase Dynamic link 时,我总是得到 nil

DynamicLinks.dynamicLinks().dynamicLink(:)

我在 Github 上发现了有用的 post,它解释了我们需要在 .plist 文件中添加域,该文件在动态 link 中使用。

这对我有用,可能对某人有帮助。

您可以像下面这样在 plist 中添加您的域:

<key>FirebaseDynamicLinksCustomDomains</key>
    <array>
        <string><YOUR_DOMAIN_NAME></string>
    </array>

确保您在域名中指定了 https:// 或 http://。

注意: 如果您想探索如何处理 iOS 13 和更高版本 iOS 的 Firebase 动态 link。