Swiftui: How to Make a Button Open a Url in Safari

SwiftUI: How do I make a button open a URL in safari?


iOS 14.0+

Using Link:

Link("Some label", destination: URL(string: "https://www.mylink.com")!)

Older versions

Button(action: {
if let url = URL(string: "https://www.mylink.com") {
UIApplication.shared.open(url)
}
}) {
Text("Some label")
}

How to create tappable url/phone number in SwiftUI

Using iOS 14 / Xcode 12.0 beta 5

Use new link feature in SwiftUI for phone and email links.

    // Link that will open Safari on iOS devices
Link("Apple", destination: URL(string: "https://www.apple.com")!)

// Clickable telphone number
Link("(800)555-1212", destination: URL(string: "tel:8005551212")!)

// Clickable Email Address
Link("apple@me.com", destination: URL(string: "mailto:apple@me.com")!)

How to load a webpage in an ovally inside a SwiftUI App vs loading in safari

You need to wrap the SFSafariViewController (which is from UIKit) into SwiftUI, since it isn't possible to do this natively right now. You should use UIViewControllerRepresentable to do this.

import SwiftUI
import SafariServices

struct MyView: View {
@State var showStackoverflow:Bool = false

var body: some View {
Button(action: { self.showStackoverflow = true }) {
Text("Open stackoverflow")
}
.sheet(isPresented: self.$showStackoverflow) {
SFSafariViewWrapper(url: URL(string: "https://stackoverflow.com")!)
}
}
}
struct SFSafariViewWrapper: UIViewControllerRepresentable {
let url: URL
func makeUIViewController(context: UIViewControllerRepresentableContext<Self>) -> SFSafariViewController {
return SFSafariViewController(url: url)
}
func updateUIViewController(_ uiViewController: SFSafariViewController, context: UIViewControllerRepresentableContext<SFSafariViewWrapper>) {
return
}
}

Swift Open Link in Safari

It's not "baked in to Swift", but you can use standard UIKit methods to do it. Take a look at UIApplication's openUrl(_:) (deprecated) and open(_:options:completionHandler:).

Swift 4 + Swift 5 (iOS 10 and above)

guard let url = URL(string: "https://stackoverflow.com") else { return }
UIApplication.shared.open(url)

Swift 3 (iOS 9 and below)

guard let url = URL(string: "https://stackoverflow.com") else { return }
UIApplication.shared.openURL(url)

Swift 2.2

guard let url = URL(string: "https://stackoverflow.com") else { return }
UIApplication.sharedApplication().openURL(url)

Open certain links in Safari from WKWebView

You can use a Coordinator in your UIViewRepresentatable to act as a navigation delegate for the WKWebView:

struct TrainerTab: UIViewRepresentable {

let request: String
private let hostingUrl: String = "https://page.tld"

func makeCoordinator() -> Coordinator {
Coordinator()
}

func makeUIView(context: Context) -> WKWebView {
return WKWebView()
}

func updateUIView(_ uiView: WKWebView, context: Context) {
uiView.navigationDelegate = context.coordinator
let url = "\(hostingUrl)/\(request)"
uiView.load(URLRequest(url: URL(string: url)!))
}

class Coordinator : NSObject, WKNavigationDelegate {
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
guard let url = navigationAction.request.url else {
decisionHandler(.allow)
}

//make some conditions based on the URL here
if myCondition {
decisionHandler(.cancel)
UIApplication.shared.open(url)
} else {
decisionHandler(.allow)
}
}
}
}

Open non-URL string in Safari (e.g. Search)

You can use x-web-search:// scheme with x-web-search://?[SearchValue].

Sample code:

let urlStr = "x-web-search://?[SearchValue]"
if let url = URL(string: urlStr) {
if UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url, options: [:]) { didEnd in
print("Did End: \(didEnd)")
}
} else {
print("Can't open URL")
}
} else {
print("Isn't URL")
}

SwiftUI on app load - redirect to web URL

You can use NavigationView with pre-selected NavigationLink: this will open as soon as the view appears.

Display your main app only after NavigationLink is closed with if.

struct ContentView: View {
var body: some View {
MainApp()
.onAppear {
UIApplication.shared.open(URL(string: "https://stackoverflow.com/")!)
}
}
}

struct MainApp: View {
var body: some View {
Text("hello")
}
}

Is it possible to open a markdown link in our app instead of Safari?

The SwiftUI environment includes a URL handler which, by default, opens links in Safari, but you can provide your own handler to override this.

Text("Hello! Example of a markdown with a link [example](https://example.com)")
.environment(\.openURL, OpenURLAction { url in
// ... set state that will cause your web view to be loaded...
return .handled
})

The OpenURLAction has to return a value of type OpenURLAction.Result - here, .handled tells the system that you have dealt with the URL yourself so the OS doesn't have to do anything else.

You could also include certain logic such that if (for example) the URLs pointed to specific hosts, you handled them, but everything else should open in Safari; in that case, you'd return .handled for the URLs you're taking responsibility for, and .systemAction for any URL where the default behaviour should be used.

Other return types include .discarded to tell the app to ignore the tap on the link, and a version of .systemAction that allows you to redefine the link that opens in Safari. I don't think either fit your use case here, though.

This post on fivestars.blog goes into more detail. Also check out the openURL and OpenURLAction documentation.



Related Topics



Leave a reply



Submit