Please help me in this issue. I have implemented universal links by following https://www.raywenderlich.com/128948/universal-links-make-connection and the problem I am getting is that when I click on a link, I am redirected to web browser instead of app. And in safari browser, when I scroll down the page, I am getting a banner which has OPEN button also. By clicking it, my app opens and the specific view controller according to the logic opens. So why it is opening in browser at first? If app is installed, it should directly open in app instead of web browser.
Following are the methods in my app delegates:
func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool {
if userActivity.activityType == NSUserActivityTypeBrowsingWeb {
guard let url = userActivity.webpageURL else {
return false
}
openViewController(url)
}
return true
}
func openViewController(url: NSURL) {
let components = NSURLComponents(URL: url, resolvingAgainstBaseURL: true)
print(components)
print(url.absoluteString)
if url.host == "refit.co" && (url.pathComponents![2] == "supplements" || url.pathComponents![2] == "equipments") {
print("This is the supplements/equipments universal link")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("Home")
let navController = self.window?.rootViewController as? UINavigationController
navController?.pushViewController(vc, animated: false)
let vc2 = storyboard.instantiateViewControllerWithIdentifier("SupplementDetail") as? VCSupplementDetail
vc2?.itemID = getID(url.query!)
vc2?.screenName = url.pathComponents![2] == "supplements" ? "Supplements" : "Equipments"
navController?.pushViewController(vc2!, animated: true)
print("Query: \(url.query)")
} else {
print("This is the url: \(url)")
print(url.host)
print(url.path)
print(url.query)
print(url.pathComponents)
}
}
It sounds like you inadvertently deactivated Universal Links. This usually happens if you tap the bypass link in the top right corner of the screen after opening a Universal Link. See this answer for details on how to reverse the process.
Related
I use in my app url scheme and I don't know why sometime when I click on URL (e.g. https://api.domain.com/menu?id=7ee5232764-0a79-4afe) iOS opens my app (correct) and 1 second later opens App Store application (not correct). This is my openUrl's method:
func application(_ application: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:] ) -> Bool {
let components = url.absoluteString.components(separatedBy: "/")
if components.contains("menus") {
let menuId = url.lastPathComponent
let menu = Menu(id: menuId)
SessionManager.shared.navigationManager.present(NavigationItem.menu(menu: menu).viewController, animated: true, completion: nil)
return true
} else {
return false
}
}
Resolved! Bug is on the web side where they have activated a JS timeout that they don't stop after app is opened.
I have a problem with the implementation of deep links in my app. I am using a notification called accenggage which can be seen here. Once I Start the SDK with the conf set in the AccengageConfig.plist file in my code as indicated in the documentation, ie I do Accengage.start() in the didFinishLaunchingWithOptions method in AppDelegate, I noticed that the function that opens the url is never called. But it will print the payload in my logs, but I cannot get access to it, in order to use it in my code. Everything works perfectly if I comment it. Please have someone used this before to try to see where I go wrong. when I open the link in safari it will lunch the app but will not print the url as I requested and neither will it open the views concerned. I taught my problem was with the deep links implementation, but that is not the case, it is rather the Accengage that I am not using it properly and will be glad if someone could have an approach on how to get the url when the push is sent with Accengage. Thanks!
func application(_ application: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
print("url \(url)")
print("url host :\(url.host as String?)")
print("url path :\(url.path as String?)")
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
if(url.host == "/details"){
let Ads_details: CollectionDetailViewController = mainStoryboard.instantiateViewController(withIdentifier: "CollectionDetailViewController") as! CollectionDetailViewController
self.window?.rootViewController = Ads_details
} else if (url.host == "/profile"){
let User_profil: UserProfileViewController = mainStoryboard.instantiateViewController(withIdentifier: "UserProfileViewController") as! UserProfileViewController
self.window?.rootViewController = User_profil
}
self.window?.makeKeyAndVisible()
return true
}
I created a keyboard extension with a scan button to open a barcode scanner in my containing app. When the scan is completed, it should navigate back to the initial app and the barcode data should be set as text to the textfield that initiated the keyboard and we clicked on scan button.
There is this app Scandit Wedge that does it the same way. But I couldn't find a way to achieve the same.
Please refer GIF below.
https://s3.amazonaws.com/id123-dev-ios/scandit.gif
Any help would be much appreciated.
There is no public API to switch to the previous app, here is the answer: https://stackoverflow.com/a/13447282/1433612
But you could do that if you know the app's bundle id and url scheme. You can find unofficial lists on internet. Assuming that you are able to recognize the source app you can do something like this in your AppDelegate:
public func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
guard let applicationBundleId = options[UIApplicationOpenURLOptionsKey.sourceApplication] as? String else {
return true
}
// Save your source application
sourceApplicationBundleId = applicationBundleId
return true
}
var sourceApplicationBundleId: String?
// Attempt to open application from which your app was opened
func openApplication() {
guard let applicationBundleId = sourceApplicationBundleId, let url = url(for: applicationBundleId) else {
return
}
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
func url(for bundleId: String) -> URL? {
guard let scheme = knownUrlSchemes[bundleId] else {
return nil
}
return URL(string: scheme)!
}
// A list of known url schemes
var knownUrlSchemes: Dictionary<String, String> = {
return ["com.google.Maps": "comgooglemaps://",
"com.facebook.Facebook": "fb://"]
}()
I'm trying to post some content to twitter from my app, and since iOs 11 unfortunately the old way don't work anymore so I'm implementing twitterKit and finding some spikes.
When I don't have the app installed, it runs the completion block below, which is weird because I had to dismiss the alert myself manually, as the alert don't have any buttons to do it.
But my real problem is that I have the twitter app installed and I'm loggued in. But I'm unable to detect it with twitter kit.
And when I press the share to twitter button, the app switch to a new view, were it asks me to connect my app to my twitter (If I'm not loggued in I have a login and password box but the result is always the same...)
When I press "Connect", the view goes back to my app and nothing happens, the completion block is never called... I'm working in iOs 11 and x-code 9 but I've tried the same aproach with iOs 10 and I get the same result. Twitter login is never detected.
This is the code I'm running, any help would be apreciated:
if (Twitter.sharedInstance().sessionStore.hasLoggedInUsers()) {
// App must have at least one logged-in user to compose a Tweet
let composer = TWTRComposerViewController.emptyComposer()
present(composer, animated: false, completion: {
print("This code never runs")
})
} else {
// Log in
Twitter.sharedInstance().logIn { session, error in
if session != nil {
// Log in succeeded / Never happens
let composer = TWTRComposerViewController.emptyComposer()
composer.delegate = self
self.present(composer, animated: true, completion: {
print ("This code never runs")
})
} else {
let alert = UIAlertController(title: "No Twitter Accounts Available", message: "You must log in before presenting a composer.", preferredStyle: .alert)
//Only happens if I don't have the twitter app installed on my device
self.present(alert, animated: false, completion: {
print ("not loggued in")
/*
manual dismission of the prompt as it don't have
any button
*/
sleep(3)
alert.dismiss(animated: true, completion: nil)
})
}
}
}
In the console I'm getting this error:
[Snapshotting] Snapshotting a view (0x105977000, UIKeyboardImpl) that has not been rendered at least once requires afterScreenUpdates:YES.
EDIT: I solved it adding this method in appDelegate:
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
return Twitter.sharedInstance().application(app, open: url, options: options)
}
As you found out, you need to let the TwitterKit to handle reopening the app when it's redirected back from twitter:
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
let twtrHandled = TWTRTwitter.sharedInstance().application(app, open: url, options: options)
return twtrHandled
}
If you have several kits there that can handle URL, this is the way I handle it (here I use also facebook SDK, and Branch SDK):
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
let branchHandled = Branch.getInstance().application(app, open: url, options: options)
let fbHandled = SDKApplicationDelegate.shared.application(app, open: url, options: options)
let twtrHandled = TWTRTwitter.sharedInstance().application(app, open: url, options: options)
return branchHandled || fbHandled || twtrHandled
}
My Swift iOS application contains two screens.
Home Page (HomePageViewController)
Start Page (StartPageViewController). A button click on Home Page takes user to this page. This page has a Cancel button, that would take user back to Home Page.
My requirement is to deep link to StartPageViewController.
I have this piece of code in AppDelegate -
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
if(url.path == "/startPage"){
let startPage: StartPageViewController = mainStoryboard.instantiateViewController(withIdentifier: "StartPageViewController") as! StartPageViewController
self.window?.rootViewController = startPage
}
self.window?.makeKeyAndVisible()
return true
}
With this code, deep link takes user to Start Page. But, on clicking Cancel button, a white screen appears rather than going back to home page. (which i think is because start page is the rootViewController).
How do I direct user to Start Page and go back to Home page on clicking Cancel.
Thanks!
When deep linking, you'll have to go through the same path you would as a user.
So, first make HomePageViewController as rootViewController and present StartPageViewController onto that programmatically.
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
if(url.path == "/startPage") {
let homePage = mainStoryboard.instantiateViewController(withIdentifier: "HomePageViewController") as! HomePageViewController
homePage.buttonClick(nil) // Make sure the action receive optional sender object
self.window?.rootViewController = homePage
}
self.window?.makeKeyAndVisible()
return true
}
Try this out and let me know how it went ^_^