I have a button in my app that opens a link via safari. There are some tasks user does in web and finally returns to app on pressing a button in browser. what I need to do is to terminate app when safari opens so that when user comes back form browser, app inits without previous data.
That's how I open link:
let adrs = "mylink"
UIApplication.shared.openURL(NSURL(string: adrs) as! URL)
How can I achieve this?
Technically you can just exit the program (e.g., exit(0)). However, you should not do so, as iOS apps should not terminate on their own. Rather clean up your UI, e.g., remove all view controllers and create new ones.
Related
I have a working universal link that works when used by another app. eg. if I write the link in notepad it will open app the app. But when I call the following inside the app that the universal link links to, it will open in safari. canOpenURL returns true.
have set up this .well-known/apple-app-site-association and also the correct intent-filter. I think its working because the links open the app when clicked outside of the app.
let url = Foundation.URL(string: "https://workingdeeplink.com/")!
if UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
This is expected behaviour. When an app passes its own universal link to open, iOS will open that link in Safari.
The purpose of this is to allow a fallback when an app cannot handle an incoming link. The logic for handling an incoming link is typically something like:
Parse the incoming link
Determine if the app can handle it
If it can, then handle the link (e.g. select a specific view or take some action)
If it can't, pass the link to open so that the user is redirected back to the web site, where the link can be handled.
This avoids the situation where a deep link opens your app and then nothing happens or an error is shown (because the app can't handle the url)
There shouldn't be a case where your app tries to open a deep link it can handle; it can simply bypass then whole deep link process and take the action that would result directly.
Currently, I have to create automation ui test with XCUI and I have some action to open external browser by default is Safari.
I need to create some uitest's behavior like this.
Go to external browser when click my button.
Check is open correct url in browser (or just open browser) ?
Go back to our app with resume state.
Is it impossible to do that ?.
Absolutely. Safari is an XCUIApplication just like any other with a bundle identifier of com.apple.mobilesafari.
To check the URL you'll tap() the URL field (it's a button when a page loads) and read the value of the URL field (at this point it's a textField). Once you're done asserting that, activate() your app and you'll be back in it (note: my tests finish after asserting so I don't have to do this, but it's the published method - you could always enter debug and find how to tap the button to return to your application in the top-left of the screen if this doesn't work).
I'm happy to provide exact code if you show me you've tried this and can't get it working, but it's pretty straightforward XCUI automation.
Providing the exact code, that worked for me
enum SafariError: Error {
case appLoadTimeout
}
let safari = XCUIApplication(bundleIdentifier: "com.apple.mobilesafari")
app.buttons["MyButtom"].tap() // MyButton launches Safari
guard safari.wait(for: .runningForeground, timeout: 5) else {
throw SafariError.appLoadTimeout
}
safari.otherElements["Address"].tap()
XCTAssertEqual(safari.textFields["Address"].value as! String, "https://check-url.com")
app.activate() //Back to my app
The previous answers work fine for an external browser. If you app happens to launch inline browsers, they won't work as there is no URL bar. You could detect the inline browser and tap the Safari button to launch it externally before checking the URL, but then you'd have to reactivate your app and close the inline browser. Many more steps.
THERE IS AN EASIER WAY THAT WILL WORK WITH BOTH BROWSER TYPES!
What do these browsers share? A share button! How can we get the URL from there? Copy will place the URL in the pasteboard, which we have access to.
app.buttons["ShareButton"].tap()
_ = copyButton.waitForExistence(timeout: Waits.short.rawValue) // a tiny wait is necessary here for the share page to open fully
app.buttons["Copy"].tap()
let URL = UIPasteboard.general.string!
There are two catches here:
When inline, app is your app. When external, it's com.apple.mobilesafari. You'll have to have logic to handle that.
You want to wait for the page to finish loading. By not doing so, you will run into flakiness. When the page is loading, there is a ReloadButton. When that goes away, you should expect to see a StopButton. If the reload button doesn't disappear, the page isn't loading completely so you may need to hit the stop button, but do so in a safe way as I have seen maybe 1% of the time the page load completes in the milliseconds between giving up on it and performing that tap - I do a quick isHittable check before tapping.
We share the App deeplinks (Universal links) with our users over email, sometimes they get wrapped by email service providers for safety.
When user taps on these wrapped deeplinks, instead of opening the App directly it opens the url in Safari.
We have a page hosted on that url. We capture the deeplink there and try to open the App using Custom URL scheme (myurlscheme://). But if the App is not installed, we try to redirect the user to the App Store page.
It all worked okay until now, but seems like Apple made some changes in Safari in the new versions of iOS (>12.3).
What’s happening now is, if the App is installed and we open the App from Safari (from Custom URL), the App Store page opens in a split second after opening our App.
This is the Javascript code that we are using:
window.location.href = 'myurlscheme://';
setTimeout(function() {
window.location.href = "https://itunes.apple.com/us/app/myapp/id123456789?ls=1&mt=8";
}, 500);
Is anyone else experiencing this. If yes, were you able to find any solution?
Update:
If we set the timeout to 4000 (i.e. 4 seconds), then it does not redirect to the App Store after launching the App.
We have an App that accepts donations and per Apple's guidelines (item 21.2) we can't do this in-app, it must open a webpage in Safari to perform the donation. We've got that bit working fine, and we can actually automatically invoke the App post donation and put the user right back where they left off. The trouble is that the Tab in Safari persists when the user returns to Safari later.
Is there a way to open an app from a webpage while simultaneously closing said webpage in Safari?
So apparently the way to do it is via Javascript. You can set the window location and then immediately close the window.
e.g.
window.location = "myapp://?stuff";
window.close;
The situation is like this:
User opens app from a website using a custom urlscheme
User does stuff in the app
User clicks button in the app to return to the website in Safari.
I have tried opening a new tab containing a javascript:window.close() but this does not work on iOS 6.1.
So my question is: Is there a way to open Safari to view the website the user left from? Either with a working new tab that closes itself or a different route?
When you open the app with your custom url scheme, pass the actual page url as an argument.
mycustomUrlScheme://mydomain.com?objectid=1234&callback_url=encoded_url
In your app, handle the url for the content info and keep the page url to open it afterwards. It will make safari open a new tab. But that should be a good start.
As far as i understand you can do it.
user opens mobile safari for example http://www.example.com
user clicks a link that is appscheme://open and the application become active
user taps a button to open safari for example http://www.example.com?q=test
for the third step you can use [[UIApplication sharedApplication]openURL:url]