Receiving nil in callback of dynamicLinks.handleUniversalLink(url) - ios

I am working on receiving firebase dynamicLinks. In restorationHandler method of App delegate, I have called DynamicLinks.dynamicLinks().handleUniversalLink(url) method of Firebase DynamicLinks to get the the actual link from shortlink.
But in callback of this method I am receiving nil in dynamiclink. So, I am unable to get the url from dynamic link received in callback. Can anyone please help me to figure this out why it is returning nil.
func application(_ application: UIApplication, continue userActivity: NSUserActivity,
restorationHandler: #escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
if let incomingURL = userActivity.webpageURL {
// it prints the passed url and working fine
debugPrint("Imcoing Url is: \(incomingURL.absoluteString)")
let linkHandled = DynamicLinks.dynamicLinks().handleUniversalLink(incomingURL) { (dynamicLink, error) in
guard error == nil else {
debugPrint("Error Found: \(error!.localizedDescription)")
return
}
//
//
if let dynamiclink = dynamicLink, let _ = dynamiclink.url {
// but below function call is not called beacause dynamicLink coming in
// callback is nil
self.handleIncomingDynamicLink(dynamiclink)
}
}
if linkHandled {
return true
} else {
// do other stuff to incoming URL?
return false
}
}
return false
}

I had the same problem and for me the reason was that I forgot to add my custom url to my info.plist as described here:
https://rnfirebase.io/dynamic-links/usage#dynamic-links-with-custom-domains
Here's a preview of the snippet you should add to your info.plist replacing string with your full dynamic link url.
<key>FirebaseDynamicLinksCustomDomains</key>
<array>
<string>https://custom.domain.io/bla</string>
<string>https://custom.domain.io/bla2</string>
</array>
I am not using react native, but the solution worked for a regular iOS implementation as well.

I have found a way Expand a short URL in Swift to get actual url or query parameters coming in short url which were nil in my case because I received dynamiclink in completion handler
DynamicLinks.dynamicLinks().handleUniversalLink(incomingURL) { (dynamicLink, error) in
//Both dynamicLink and error were nil here in my case
}
nil. These lines of code will do the same in order to get actual url or query parameters from short URL.
URLSession.shared.dataTask(with: incomingURL) { (data, response, error) in
if let actualURL = response?.url {
// you will get actual URL from short link here
// e.g short url was
// https://sampleuniversallink.page.link/hcabcx2fdkfF5U
// e.g actual url will be
// https://www.example.com/somePage?quertItemkey=quertItemvalue...
}
}.resume()

Related

Handling dynamic link from Firebase in swift

I have made a dynamic link in Firebase, which op my iOS app, when I click it.
The problem is, that I can't print information about the link.
I use this function in the AppDelegate file to handle the dynamic link:
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: #escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
print("Handeling dynamic link")
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 {
// Maybe do other things with our incoming url
return false
}
}
return false
}
When I click on a dynamic link and open the app, none of the print statements is printed to the console.
It seems like this function is never tapped into.
The handleDynamicLink function is:
func handleIncomingDynamicLink(_ dynamicLink: DynamicLink) {
guard let url = dynamicLink.url else {
print("That is weird. My dynamic link object has no url")
return
}
print("Your incoming link parameter is \(url.absoluteString)")
}
I want to print information about the url so I can debug and use the information in the url to redirect to pages in the app.
When I'm testing this, I run the app on an iPhone connected to my mac.
I don't run it on the iOS simulator.
The code in your UIApplication delegate method looks good. The only difference I see with the way you have yours compared to mine is I'm returning true in the last line & you're returning false.
By the way, put breakpoints in that UIApplication delegate method & let me know if you're ever even getting to the first line in that delegate method. Are you able to hit any breakpoints in your handleIncomingDynamicLink() method?
Also, try adding this in applicationDidBecomeActive:
func applicationDidBecomeActive(_ application: UIApplication) {
guard let url = self.launchURL else { return }
self.launchURL = nil
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: { // wait to init. notifs.
DynamicLinks.dynamicLinks().handleUniversalLink(url) { (dynamiclink, error) in
if let dynamiclink = dynamiclink {
self.handleIncomingDynamicLink(dynamiclink)
}
}
})
}
And add this:
func application(_ app: UIApplication,
open url: URL,
options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
print("RECEIVED A URL THROUGH A CUSTOM SCHEME: \(url.absoluteString)")
if let dynamicLink = DynamicLinks.dynamicLinks().dynamicLink(fromCustomSchemeURL: url) {
self.handleIncomingDynamicLink(dynamicLink)
return true
} else { // Maybe handle Google or Facebook sign-in here
return false
}
}

iOS Firebase Dynamic link not handled on cold start iOS 14

When opening dynamic links on my device, my function in SceneDelegate that handles dynamic links runs fine while the app is running in the background but not when the app is completely shut off. When I do click the dynamic link while the app is off, the app opens but the dynamic link is not handled. My scene delegate function looks like this:
SceneDelegate Function
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
guard let _ = (scene as? UIWindowScene) else { return }
if let incomingURL = userActivity.webpageURL {
print("Incoming URL is \(incomingURL)")
_ = 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)
}
}
}
}
any help understanding this issue is greatly appreciated!
Since your target is iOS 14 , You can use latest APIs,
So you can use .onOpenURL() modifier on any view.
.onOpenURL { url in
_ = DynamicLinks.dynamicLinks().handleUniversalLink(url) { (dynamicLink, error) in
guard error == nil else{
print("Found an error! \(error!.localizedDescription)")
return
}
if let dynamicLink = dynamicLink {
self.handleIncomingDynamicLink(dynamicLink)
}
}
}
I was having the same issue, but I used the solution proposed from #Yodagama and it works totally fine. In my case I am loading a firebase dynamic link. The only problem I am facing is that if the user doesn't have the app installed, the link first redirects you to apple store to download it and once you have it you have to open the link again in order to perform the function.
I am putting my code here, hope it helps somebody:
import SwiftUI
import Firebase
#main
struct Universal_Link_SwiftUI2_0App: App {
init() {
FirebaseApp.configure()
}
var body: some Scene {
WindowGroup {
ContentView().onOpenURL { url in
_ = DynamicLinks.dynamicLinks().handleUniversalLink(url) { (dynamicLink, error) in
guard error == nil else{
print("Found an error! \(error!.localizedDescription)")
return
}
if let dynamicLink = dynamicLink {
self.handleIncomingDynamicLink(dynamicLink)
}
}
}
}
}

Dynamic link object has no url

I created the DynamicLink for my firebase project when I am trying to receive the link I am getting "That's weird. My dynamic link object has no url".
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 handleIncomingDynamicLink(_ dynamicLink: DynamicLink){
guard let url = dynamicLink.url else{
print("That's weird. My dynamic link object has no url")
return
}
print("Your incoming link parameter is\(url.absoluteString)")
}
After checking all the blogs and posted this issue on firebase, I didn't find any solution for this but I came up with this concrete solution and it will work definitely
here: dynamicLinkURL is your main dynamic link and shortHandURL is your deeplink URL which is associated with your dynamic link. I hope the below snippet will help you.
func dynamicLinkhandler(_ dynamicLinkURL: URL, onCompletion: #escaping(_ success: Bool) -> Void) {
URLSession.shared.dataTask(with: dynamicLinkURL) { (data, response, error) in
guard error == nil else {
print("Found Error \(String(describing: error?.localizedDescription)))")
return
}
guard let shortHandURL = response?.url, shortHandURL != dynamicLinkURL else {
print("Thats Weird, my dynamic link has no URL")
onCompletion(false)
return
}
onCompletion(true)
}.resume()
}
Double check that the bundle id you set up in the dynamic link wizard creation within the firebase console it's the one you are running the app into.
I have three different bundle ids (dev, enterprise, production) and, for instance, if a set in the link the production bundle id but the app runs the dev bundle id, instead of returning back some error it returned an honest dynamicLink object but with a nil value in the url.

iOS- how to get dynamic short links with custom parameters firebase

I want to send parameter through dynamic link and also to receive the same.
I have passed the custom parameter through my short dynamic link. Here is my link: https://pc988.app.goo.gl/vQaV?test=1
And I am using the following code to receive the dynamic link:
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
if let dynamicLink = DynamicLinks.dynamicLinks()?.dynamicLink(fromCustomSchemeURL: url){
self.handleIncomingDynamicLink(dynamicLink: dynamicLink)
return true
}
else{
let handled = FBSDKApplicationDelegate.sharedInstance().application(app, open: url, options: options)
return handled
}
}
#available(iOS 8.0, *)
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: #escaping ([Any]?) -> Void) -> Bool {
if let incomingURL = userActivity.webpageURL{
let linkHandled = DynamicLinks.dynamicLinks()!.handleUniversalLink(incomingURL, completion:{ [weak self] (dynamiclink, error) in
guard let strongSelf = self else{ return }
if let dynamiclink = dynamiclink, let _ = dynamiclink.url {
strongSelf.handleIncomingDynamicLink(dynamicLink: dynamiclink)
}
})
return linkHandled
}
return false
}
func handleIncomingDynamicLink(dynamicLink: DynamicLink) {
if dynamicLink.matchConfidence == .weak{
}else {
guard let pathComponents = dynamicLink.url?.pathComponents else { return }
for nextPiece in pathComponents{
}
}
print("incoming link \(dynamicLink.url)")
}
And my exact problem was, I cannot get the 'test' parameter that I passed in dynamic short link which I mentioned above.
Help me to get rid off this problem.
To append custom parameter you need to append the parameter to the deep link, not to the dynamic link.
In your example the deep link is https://www.fitview.com/ (you can see this in debug page https://pc988.app.goo.gl/vQaV?d=1).
To accomplish your goal, set the deep link to https://www.fitview.com?test=1 , create dynamic link, and then shorten dynamic link.

No Data in Array after appending using Swift and xcode

I am trying to download images from a url and then save them in an array of NSData.
I have a Class called Data Manager in which all my data is stored as well as functions for downloading images and getting data from URL.
In the same class I declare a variable called imageData of type [NSData] and let it equal an empty array as follows:
var imageData: [NSData] = []
here is what my other 2 functions look like:
func getDataFromUrl(url:NSURL, completion: ((data: NSData?, response: NSURLResponse?, error: NSError? ) -> Void)) {
NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) in
completion(data: data, response: response, error: error)
}.resume()
}
func downloadImage(url: NSURL){
print("Download Started")
print("lastPathComponent: " + (url.lastPathComponent ?? ""))
getDataFromUrl(url) { (data, response, error) in
dispatch_async(dispatch_get_main_queue()) { () -> Void in
guard let data = data where error == nil else { return }
print(response?.suggestedFilename ?? "")
print("Download Finished")
self.imageData.append(data)
print("you have \(self.imageData.count)")
}
print("you still do have \(self.imageData.count)")
}
}
I call these functions in my app Delegate class under the function didFinishLaunchingWithOptions as so
let dataManager = DataManager()
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
dataManager.URLStringArray.removeAll()
for url in dataManager.objects.imageURLS {
dataManager.URLStringArray.append(url)
}
for url in dataManager.URLStringArray {
dataManager.downloadImage(NSURL(string: url)!)
print(url)
}
return true
}
In my view controller I go to get the data in the image array via following function:
func returnImageData() -> [NSData] {
print("your image count is \(imageData.count))")
return imageData
}
but the array is empty! Even though through the whole process I noticed that the array was becoming larger and larger because the print to the logs were showing the array increasing!
Thanks!
Since you are using async call to download the image data, at the the time you are printing the count of the imageData the image is not yet downloaded and so the array is not yet populated. Of course this is assuming that you are using the right property names as Eric.D has pointed out.

Resources