Skip to content

Instantly share code, notes, and snippets.

@tommy-holmes
Last active December 28, 2022 13:41
Show Gist options
  • Save tommy-holmes/39cd8bcc3ec1039b9886440dec503761 to your computer and use it in GitHub Desktop.
Save tommy-holmes/39cd8bcc3ec1039b9886440dec503761 to your computer and use it in GitHub Desktop.
A SwiftUI view for presenting a `SFSafariViewController` with a URL Binding that presents nicely in the UI.
import SwiftUI
import SafariServices
public struct SafariView: View {
@Binding var url: URL?
var entersReaderIfAvailable: Bool = false
public var body: some View {
SafariViewRepresentable(url: $url, enterReader: entersReaderIfAvailable)
.navigationBarHidden(true)
.ignoresSafeArea()
}
}
fileprivate struct SafariViewRepresentable: UIViewControllerRepresentable {
@Binding var url: URL?
let enterReader: Bool
func makeUIViewController(context: Context) -> SFSafariViewController {
let config = SFSafariViewController.Configuration()
config.entersReaderIfAvailable = enterReader
let vc = SFSafariViewController(url: url!, configuration: config)
vc.delegate = context.coordinator
return vc
}
func updateUIViewController(_ controller: SFSafariViewController, context: UIViewControllerRepresentableContext<SafariViewRepresentable>) { }
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
}
extension SafariViewRepresentable {
fileprivate final class Coordinator: NSObject, SFSafariViewControllerDelegate {
let parent: SafariViewRepresentable
init(_ parent: SafariViewRepresentable) {
self.parent = parent
}
func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
parent.url = nil
}
}
}
@tommy-holmes
Copy link
Author

FYI this is iOS 14.0+ just replace .ignoresSafeArea() with .edgesIgnoringSafeArea(.all) for iOS 13.X

@brockweaver
Copy link

Hey Tommy -- thank you for this, it is exactly what I needed. I tried a few other approaches google found and they didn't work as advertised. Yours worked first time without hitch.

Is there a way to prevent having the SFSafariViewController save session cookies using this method? Or alternatively, wiping out any session cookies prior to displaying the view?

I'm using this for OAuth login to a site I don't control and the cookies seem to be persisted during the lifetime of my app executing. Restarting the app results in no cookies, so they appear to be cleaned up at app shutdown.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment