URL Scheme sometime launch App Store after application - ios

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.

Related

How to debug iOS App when opened from TodayExtension with openUrl?

I have mini-app with Today Extension and I created a custom URL Scheme.
Then after clicking a UIButton in the extension, I've called the open function like
extensionContext?.open(URL(string: "todayextensionexample://inform")!, completionHandler: nil)
The application has started successfully but I cannot debug it.
I try 3 different approaches.
First of all for open debugging Edit Scheme -> Info -> Wait for executable to be launched for executable to be launched in Application scheme but the application waits and there's no launch so there's no debug.
My ( open url: URL ) function is like below:
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
NotificationCenter.default.post(name: NSNotification.Name.urlOpenedNotification, object: nil, userInfo: nil)
return true
}
in viewDidLoad method of the ViewController;
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(notificationHandler(_:)), name: NSNotification.Name.urlOpenedNotification, object: nil)
}
This was my second approach.
The 3. approach is that using parsing the URL parameters and logging it like below:
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
let sendingAppID = options[.sourceApplication];
print("source application = \(sendingAppID ?? "Unknown") ")
guard let components = NSURLComponents(url: url, resolvingAgainstBaseURL: true),
let path = components.path,
let params = components.queryItems else {
print("Invalid URL or album path missing")
return false
}
print("components > ", components)
print("path > ", path)
print("params >", params)
var param: [String: Any] = ["components": components, "path": path, "params": params];
NotificationCenter.default.post(name: NSNotification.Name.urlOpenedNotification,
object: nil,
userInfo: param)
return true
}
In 3. approach, I tried that Notification & printing some variables.
Before my questions; I change some of print()'s to NSLog() but in the Device -> Show Logs there's nothing works.
Application has opened with openUrl but I cannot debug it because if I start the TodayExtension target the Application not debugging and otherside if I start Application target, when I click the TodayExtension button then open the app again when it background
func application(_ app: UIApplication, open url: URL ...)
function is not working. I've seen the debugs of the real device but there's nothing to see.
Is there any way to after clicking the button on Today Extension then Xcode has started the main application target and I will able to see the all of the logs?
How can I debug it and see check if its successfully working?
1) Override an initializer in your App Delegate, and add there sleep call.
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
override init() {
sleep(10000)
}
...
}
2) Install this app on your device or simulator.
3) Put a breakpoint in your code.
4) From the extension, trigger the deeplink.
5) While app is opened and in sleep, connect your Xcode debugger to your app via Xcode app menu (Debug->Attach To Process->< your app name >). This will instantly wake up your app and it will fall into the breakpoint immediately.

Back link to previous app from containing app progmatically in case of deeplinks

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://"]
}()

twitterKit Login completion block is never executed

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
}

Universal Links is showing banner on top of Safari browser

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.

How to redirect back to my iOS app after logging in on FitBit login page?

I am developing a very basic iOS app with Swift. Just to read the heart rate data. I am using SFSafariViewController. As known, I first need to register my app on dev.fitbit.com. The registration form requires a callback URL to be entered.
After logging in successfully, FitBit always redirects me back to that entered callback URL. What should I do/code/configure to be able to redirect user back to my iOS app after logging in successfully?
What you need to do is to add the application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool function to your AppDelegate and then create an url scheme for your application as an identifier. To create an url scheme go to your application target > Info > URL Types (at the bottom). Then just add the following in your AppDelegate:
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
DispatchQueue.main.async {
// Conctrol so that we´re coming from the right application
if (url.scheme == "The url scheme that you created"){
// Navigate to the viewController you want
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "WebView") as! WebViewController
self.window?.rootViewController!.present(controller, animated: true, completion: { () -> Void in
})
}
}
return true
}
Try using below 3 steps in your application.
You are using "fitbit", so I am considering your are using OAuth2.0 for login and get access-token.
Step 1 : Set up you URL Schemes.
Step 2 : In your AppDelegate class
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
if (url.host == "oauth-swift") {
OAuthSwift.handle(url: url)
}
return true
}
In Above function what we did is, we check the URL comes to handleOpenUrl method, and check weather it is the right url call back is coming or not.
Step 3 : Set the proper call back URL in you OAuth Handler.
oauthswift = OAuth2Swift(
consumerKey: "********",
consumerSecret: "********",
authorizeUrl: "your authorisation url",
responseType: "token"
)
let handle = oauthswift.authorize(
withCallbackURL: URL(string: "oauth-swift://oauth-callback/fitbit")!,
scope: "your application scope", state:"state",
success: { credential, response, parameters in
print(credential.oauth_token)
},
failure: { error in
print(error.localizedDescription)
}
)
In above step, we set the call back url starting with "oauth-swift:", so it will be work as a host of your call back url.
Image and Code Courtesy : I have tried to explain a solution of your
problem in easy words. And all information of this answers are
originally documented and explained on this URL :
https://github.com/OAuthSwift/OAuthSwift

Resources