would appreciate any help. We have implemented handling of universal links in our app and I am struggling with the following issues:
Universal Links opens when the app is running in the background (working fine)
When running on the device with iOS13 installed, opening a universal link only works properly if the app is running in the background. If it has been terminated, after tapping the
link the app is getting launched but this method not called
application(continue userActivity:.., restorationHandler:..)
Any ideas? Appreciate!
enter code here
var window: UIWindow?
var tabBarController1: UITabBarController?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool
{
presentAppLaunchVC()
return true
}
func presentVC(navController : UINavigationController)
{
if var topController = UIApplication.shared.keyWindow?.rootViewController {
while let presentedViewController = topController.presentedViewController {
topController = presentedViewController
}
topController.present(navController, animated: false, completion: nil)
}
}
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: #escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
if userActivity.activityType == NSUserActivityTypeBrowsingWeb
{
guard let url = userActivity.webpageURL else {
return false
}
if !isValidDeepLink(web_url: url)
{
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
else
{
scrapDeepLinkingUrl(url : url)
}
}
return true
}
func isValidDeepLink(web_url :URL) -> Bool
{
guard let components = URLComponents(url : web_url,resolvingAgainstBaseURL : true) else {
return false
}
guard let host = components.host else {
return false
}
switch host {
case "www.domain.com":
return true
default:
return false
}
}
func scrapDeepLinkingUrl(url : URL)
{
}
else
{
presentAppLaunchVC()
}
}
func presentAppLaunchVC()
{
let storyBoard = UIStoryboard(name: storyboard_name, bundle: nil)
let screen = storyBoard.instantiateViewController(withIdentifier: identifier)
if identifier == "dashboardVC" {
tabBarController1 = screen as? UITabBarController
}
self.window?.rootViewController = screen
}
You need to check the URL in didFinishLaunchingWithOptions method as well.
It can be an URL:
launchOptions[UIApplicationLaunchOptionsURLKey]
or it can be an Universal link:
launchOptions[UIApplicationLaunchOptionsUserActivityDictionaryKey]
What I would do is add conditional scene delegate support. That way, you would get the message in scene(_:willConnectTo:). Okay, this is going to be more work, but you need to get in sync with the native scene support in iOS 13 and later, and this seems to be the moment to do so.
Related
I'm developing an app that can receive Firebase's Dynamic Link. What I want is when a user click a Dynamic Link, the app redirects it to a certain UIViewController. So I have a code that looks like this on my AppDelegate.swift file:
#available(iOS 9.0, *)
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool {
//return GIDSignIn.sharedInstance().handle(url)
return application(app, open: url, sourceApplication: options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String, annotation: "")
}
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
// On progress
if let dynamicLink = DynamicLinks.dynamicLinks().dynamicLink(fromCustomSchemeURL: url) {
print("open url = open dynamic link activity")
print("url = \(dynamicLink)")
let destinationVC = UIStoryboard(name: "DynamicLink", bundle: nil).instantiateViewController(withIdentifier: "DynamicLinkView") as? DynamicLinkVC
self.window?.rootViewController?.navigationController?.pushViewController(destinationVC!, animated: true)
} else {
print("open url = none")
}
return GIDSignIn.sharedInstance().handle(url)
}
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: #escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
// On progress
let handled = DynamicLinks.dynamicLinks().handleUniversalLink(userActivity.webpageURL!) { (dynamiclink, error) in
print("dynamic link = \(dynamiclink)")
}
if handled {
let destinationVC = UIStoryboard(name: "DynamicLink", bundle: nil).instantiateViewController(withIdentifier: "DynamicLinkView") as? DynamicLinkVC
self.window?.rootViewController?.navigationController?.pushViewController(destinationVC!, animated: true)
}
return handled
}
So what happened when I click the link the app opens up immediately but it doesn't redirects to the desired UIViewController that I wanted (in this case destinationVC). It directly went to the login page as usual. But in the debug area, the link appears like this =
dynamic link = Optional(https://xxxx], match type: unique, minimumAppVersion: N/A, match message: (null)>)
Unfortunately I couldn't record the log messages when the app is not built by Xcode.
I'm very confused by this, what's wrong with my code? I'm new to iOS development so I'm not sure where did I do wrong. If you need more information feel free to ask and I will provide it to you. Any help would be appreciated. Thank you.
If your rest-of-code is working fine, and you are just facing issue while navigating to another view controller, then this solution will work for you.
If you want to open particular ViewController, while clicking on dynamic link, then update your code written within restorationHandler, below updated code will help you to redirect/navigate to particular View Controller
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: #escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
// On progress
let handled = DynamicLinks.dynamicLinks().handleUniversalLink(userActivity.webpageURL!) { (dynamiclink, error) in
print("dynamic link = \(dynamiclink)")
}
if handled {
let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "DynamicLink", bundle: nil)
if let initialViewController : UIViewController = (mainStoryboardIpad.instantiateViewController(withIdentifier: "DynamicLinkView") as? DynamicLinkVC) {
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
}
return handled
}
Hope this will resolve your issue.
I'm trying deeplink to open particular page in app on click of shared link from other app/from safari, URL opens the app but unable to take application on particular page i,e, unable to read link (custom URL). This is my custom URL :- WOT://tradeDetail
If anyone knows where i'm going wrong, please help
here is screenshot and code
var window: UIWindow?
var scheme = "WOT"
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
ApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions)
GMSPlacesClient.provideAPIKey(WOT.googlePlaceAPIKey)
if let url = launchOptions?[.url] as? URL {
return handle(url: url)
}
return true
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
return handle(url: url)
}
func handle(url: URL) -> Bool {
switch url.absoluteString {
case "\(scheme)://tradeDetail" : do {
let sb = UIStoryboard(name: "Main", bundle: .main)
let detailView = sb.instantiateViewController(withIdentifier: "SearchedPlaceDetailVC") as? SearchedPlaceDetailVC
window?.rootViewController = detailView
window?.makeKeyAndVisible()
}
default: return false
}
return true
}
You need to call below function to navigate particular page
func application(_ application: UIApplication, continue userActivity:
NSUserActivity, restorationHandler: #escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
let myUrl: String? = userActivity.webpageURL?.absoluteString
if myUrl?.range(of: "tradeDetail") != nil {
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
let yourViewController = storyboard.instantiateViewController(withIdentifier: “YourViewController”) as? YourViewController
self.window?.rootViewController = yourViewController
self.window?.makeKeyAndVisible()
}
return true
}
I am using universal linking in my project.
I have made apple-app-site-association file in server.
I enable in developer account, Xcode for associate domains and I wrote
applinks:www.laundry.com
The code used in AppDelegate is:-
//Universal links in swift delegatemethod.
func application(_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: #escaping ([Any]?) -> Void) -> Bool
{
if userActivity.activityType == NSUserActivityTypeBrowsingWeb {
let url = userActivity.webpageURL!
let userurl = url.absoluteString
// print(url.absoluteString)
//handle url
if defaultValues.value(forKey: accessToken) != nil
{
print("user url is:",userurl)
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Pickup", bundle: nil)
let innerPage: PickupController = mainStoryboard.instantiateViewController(withIdentifier: "PickupController") as! PickupController
innerPage.selectedfrom = "Deeplink"
self.window?.rootViewController = innerPage
}else{
setRootControllerBeforeLogin()
}
}
return true
}
But it is not working, please help to me.
I once used dynamic links of firebase, and override another function in appDelegate like below.
func application(_ application:UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any]) -> Bool {
print("I have received a URL through custom url scheme : \(url.absoluteString)")
// tot do with dynamic link....
if let dynamicLink = DynamicLinks.dynamicLinks().dynamicLink(fromCustomSchemeURL: url) {
return true
} else {
// handle others like twitter or facebook login
}
}
Do it on App delegate
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: #escaping ([Any]?) -> Void) -> Bool {
if let url = userActivity.webpageURL {
let component = URLComponents.init(string: url.absoluteString)!
print(component.path)
}
return true
}
3D Touch is working fine when I press it on the home screen, but not showing the navigation and tab bar, How can I present Navigation and Tab bar using 3D Touch? Don't know how to Override point for customization after application launch.
Grazie Mille
class AppDelegate: UIResponder, UIApplicationDelegate {
enum ShortcutIdentifier: String {
case First
case Second
case Third
case Fourth
//Initializers
init?(fullType: String) {
guard let last = fullType.components(separatedBy: ".").last else { return nil }
self.init(rawValue: last)
}
//Properties
var type: String {
return Bundle.main.bundleIdentifier! + ".\(self.rawValue)"
}
}
var window: UIWindow?
/// Saved shortcut item used as a result of an app launch, used later when app is activated.
var launchedShortcutItem: UIApplicationShortcutItem?
func handleShortCutItem(_ shortcutItem: UIApplicationShortcutItem) -> Bool {
var handled = false
// Verify that the provided shortcutItem type is one handled by the application.
guard ShortcutIdentifier(fullType: shortcutItem.type) != nil else { return false }
guard let shortCutType = shortcutItem.type as String? else { return false }
let storyboard = UIStoryboard(name: "Main", bundle: nil)
var vcc = UIViewController()
switch (shortCutType) {
case ShortcutIdentifier.First.type:
vcc = storyboard.instantiateViewController(withIdentifier: "VC1")
handled = true
break
case ShortcutIdentifier.Second.type:
vcc = storyboard.instantiateViewController(withIdentifier: "VC2")
handled = true
break
case ShortcutIdentifier.Third.type:
vcc = storyboard.instantiateViewController(withIdentifier: "VC3")
handled = true
break
case ShortcutIdentifier.Fourth.type:
vcc = storyboard.instantiateViewController(withIdentifier: "VC4")
handled = true
break
default:
break
}
// Display the selected view controller
self.window?.rootViewController?.present(vcc, animated: true, completion: nil)
return handled
}
func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: #escaping (Bool) -> Void) {
let handledShortCutItem = handleShortCutItem(shortcutItem)
completionHandler(handledShortCutItem)
}
func applicationDidBecomeActive(_ application: UIApplication) {
guard launchedShortcutItem != nil else { return }
//handleShortCutItem(shortcut)
launchedShortcutItem = nil
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
// If a shortcut was launched, display its information and take the appropriate action
if let shortcutItem = launchOptions?[UIApplicationLaunchOptionsKey.shortcutItem] as? UIApplicationShortcutItem {
launchedShortcutItem = shortcutItem
}
return true
}
How can I present Navigation and Tab bar using 3D Touch
The same way you do it during the normal run of your app. You should not be doing some special thing in response to the user pressing the shortcut item (i.e. your self.window?.rootViewController?.present, which in effect merely puts up a temporary facade); you should be navigating to the actual area of your real app that the shortcut item corresponds to.
I am trying to add 3D Touch Shortcuts to an application, I have managed to have the shortcuts appear when using 3DTouch on the app icon from the homescreen; however when using the shortcut the application crashes on load and I am unsure why.
I have managed to get the application to load for the bookmarks shortcut but it does not initiate the BookmarksViewController, it just loads the InitialViewController.
The application is embedded within a UITabBarController and a UINavigationController for each Tab. Both View Controllers I am trying to load are in different tabs but the first view in the navigation controller stack.
Does anyone know where I am going wrong ?
info.plist file
App Delegate
enum ShortcutItemType: String {
case Bookmarks
case Favourites
init?(shortcutItem: UIApplicationShortcutItem) {
guard let last = shortcutItem.type.componentsSeparatedByString(".").last else { return nil }
self.init(rawValue: last)
}
var type: String {
return NSBundle.mainBundle().bundleIdentifier! + ".\(self.rawValue)"
}
}
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
if let shortcutItem = launchOptions?[UIApplicationLaunchOptionsShortcutItemKey] as? UIApplicationShortcutItem {
handleShortcutItem(shortcutItem)
}
return true
}
private func handleShortcutItem(shortcutItem: UIApplicationShortcutItem) {
if let rootViewController = window?.rootViewController, let shortcutItemType = ShortcutItemType(shortcutItem: shortcutItem) {
let sb = UIStoryboard(name: "main", bundle: nil)
let favouritesVC = sb.instantiateViewControllerWithIdentifier("FavouritesVC") as! FavouritesTableViewController
let bookmarksVC = sb.instantiateViewControllerWithIdentifier("BookmarksVC") as! BookmarksNotesViewController
switch shortcutItemType {
case .Bookmarks:
rootViewController.presentViewController(bookmarksVC, animated: true, completion: nil)
break
case .Favourites:
rootViewController.presentViewController(favouritesVC, animated: true, completion: nil)
break
}
}
}
func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void) {
handleShortcutItem(shortcutItem)
}
}
Storyboard ID
These are the StoryboardID for the View Controllers.
I think you forgot the 's' in com.appName.Bookmark
Or you need to remove the 's' from Bookmarks here:
enum ShortcutItemType: String {
case Bookmarks
case Favourites
Instead, try using a shortcut like this:
if shortcutItem.type == "com.appName.Bookmark"
#available(iOS 9.0, *)
func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void) {
if shortcutItem.type == "com.appName.Bookmark" {
}
}