Skip to content

Instantly share code, notes, and snippets.

@drucelweisse
Last active March 29, 2025 07:30
Show Gist options
  • Save drucelweisse/77fe56d3461451d0cb6c6e7e455ed792 to your computer and use it in GitHub Desktop.
Save drucelweisse/77fe56d3461451d0cb6c6e7e455ed792 to your computer and use it in GitHub Desktop.
struct ContentView: View {
@State var urlString = "https://www.google.com"
@State var url: URL?
var body: some View {
NavigationStack {
WebViewReader { proxy in
Webview(url: url ?? URL(string: "https://www.google.com")!)
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button("Reload") {
proxy.reload()
}
}
ToolbarItem(placement: .topBarLeading) {
Button("Back") {
proxy.goBack()
}
}
}
.navigationTitle(proxy.title)
.navigationBarTitleDisplayMode(.inline)
}
.safeAreaInset(edge: .bottom) {
TextField("Enter URL", text: $urlString)
.textFieldStyle(.roundedBorder)
.onSubmit {
url = URL(string: urlString)
}
.padding()
.background(.ultraThinMaterial)
}
.onChange(of: url) {
urlString = $0?.absoluteString ?? ""
}
}
}
}
struct WebViewProxy {
fileprivate var box: Box<WKWebView?>? = Box(nil)
var title: String {
box?.value?.title ?? ""
}
func reload() {
box?.value?.reload()
}
func goBack() {
box?.value?.goBack()
}
}
extension EnvironmentValues {
@Entry var box: Box<WKWebView?>?
}
class Box<T> {
var value: T
init(_ value: T) {
self.value = value
}
}
struct WebViewReader<C: View>: View {
@State var proxy = WebViewProxy()
let content: (WebViewProxy) -> C
var body: some View {
content(proxy)
.environment(\.box, proxy.box)
}
}
struct Webview: UIViewRepresentable {
let url: URL
func makeUIView(context: Context) -> WKWebView{
let webView = WKWebView()
webView.load(URLRequest(url: url))
return webView
}
func updateUIView(_ uiView: WKWebView, context: Context) {
if uiView.url != url {
uiView.load(URLRequest(url: url))
}
context.environment.box?.value = uiView
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment