Reputation: 1431
There is another post on SO regarding this issue but it's from a while back and only deals with UIKit, not SwiftUI. I have SFSafariViewController working perfectly, and am using it via a programmatic NavigationLink.
The issue is that the tappable area of the Done button is too small. I can only tap on the "ne" of the word "Done" and only at a certain angle. It's very strange and I haven't been able to solve the issue. The rest of the buttons all work perfectly.
If I change to using it modally via a sheet, the Done button works perfectly, but I need to use it via a NavigationLink.
I just need to solve the problem with the tappable area of the Done button.
Thanks!
Here's my SFSafariViewController:
import SwiftUI
import SafariServices
struct SafariView: UIViewControllerRepresentable {
@Environment(\.dismiss) var dismiss
let url: URL
func makeUIViewController(context: Context) -> SFSafariViewController {
let vc = SFSafariViewController(url: url)
vc.preferredControlTintColor = .tintColor
vc.delegate = context.coordinator
return vc
}
func updateUIViewController(_ vc: SFSafariViewController, context: Context) {}
class Coordinator: NSObject, SFSafariViewControllerDelegate {
var dismissAction: DismissAction?
func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
dismissAction?()
}
}
func makeCoordinator() -> Coordinator {
let coordinator = Coordinator()
coordinator.dismissAction = dismiss
return coordinator
}
}
Here's my view:
import SwiftUI
struct HomeView: View {
@State private var isBtnActive: Bool = false
var body: some View {
NavigationLink(
destination: SafariView(url: URL(string: "https://www.example.com")!)
.navigationBarHidden(true),
isActive: $isBtnActive,
label: {
EmptyView()
}
)
.accessibilityHidden(true)
VStack(spacing: 0) {
Spacer()
Button("Show Website") {
isBtnActive = true
}
Spacer()
}
}
}
Upvotes: 2
Views: 304
Reputation: 26
I have found a solution in SwiftUI regarding this topic.
This code embeds a SafariViewController
into a NavigationView
and the "Done" button is working. The only thing that doesn't work is the swipe back gesture.
import SwiftUI
import SafariServices
struct SafariWebView: UIViewControllerRepresentable {
let url: URL
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: Context) -> UINavigationController {
let safariVC = SFSafariViewController(url: url)
safariVC.delegate = context.coordinator
let navController = UINavigationController(rootViewController: safariVC)
navController.setNavigationBarHidden(true, animated: false)
return navController
}
func updateUIViewController(_ uiViewController: UINavigationController, context: Context) {}
class Coordinator: NSObject, SFSafariViewControllerDelegate {
var parent: SafariWebView
init(_ parent: SafariWebView) {
self.parent = parent
}
func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
parent.presentationMode.wrappedValue.dismiss()
}
}
}
struct AppLink: View {
var url: String
var body: some View {
SafariWebView(url: URL(string: url)!)
.ignoresSafeArea()
.navigationBarBackButtonHidden(true)
}
}
#Preview {
AppLink(url: "https://www.example.com")
}
And then you can use it with a NavigationLink
:
NavigationStack {
NavigationLink("Link App", destination: AppLink(url: "https://www.example.com"))
}
Upvotes: 1