Following @AlexanderVasenin's instructions, I created an essence that works great.
Sample code here
Assuming index.html is the page you are trying to load.
- Override the
navigator.geolocation.getCurrentPosition HTML method that is used to request location information using this script.
let scriptSource = "navigator.geolocation.getCurrentPosition = function(success, error, options) {window.webkit.messageHandlers.locationHandler.postMessage('getCurrentPosition');};" let script = WKUserScript(source: scriptSource, injectionTime: .atDocumentEnd, forMainFrameOnly: true) contentController.addUserScript(script)
so whenever a webpage tries to call navigator.geolocation.getCurrentPosition , we redefine it by calling func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage)
- The
userContentController method then retrieves the location data from the CLLocationManager and calls the method on the web page to process this response. In my case, this is the getLocation(lat,lng) method.
This is the complete code.
ViewController.swift
import UIKit import WebKit import CoreLocation class ViewController: UIViewController , CLLocationManagerDelegate, WKScriptMessageHandler{ var webView: WKWebView? var manager: CLLocationManager! override func viewDidLoad() { super.viewDidLoad() manager = CLLocationManager() manager.delegate = self manager.desiredAccuracy = kCLLocationAccuracyBest manager.requestAlwaysAuthorization() manager.startUpdatingLocation() let contentController = WKUserContentController() contentController.add(self, name: "locationHandler") let config = WKWebViewConfiguration() config.userContentController = contentController let scriptSource = "navigator.geolocation.getCurrentPosition = function(success, error, options) {window.webkit.messageHandlers.locationHandler.postMessage('getCurrentPosition');};" let script = WKUserScript(source: scriptSource, injectionTime: .atDocumentEnd, forMainFrameOnly: true) contentController.addUserScript(script) self.webView = WKWebView(frame: self.view.bounds, configuration: config) view.addSubview(webView!) webView?.uiDelegate = self webView?.navigationDelegate = self webView?.scrollView.delegate = self webView?.scrollView.bounces = false webView?.scrollView.bouncesZoom = false let url = Bundle.main.url(forResource: "index", withExtension:"html") let request = URLRequest(url: url!) webView?.load(request) } func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { if message.name == "locationHandler",let messageBody = message.body as? String { if messageBody == "getCurrentPosition"{ let script = "getLocation(\(manager.location?.coordinate.latitude ?? 0) ,\(manager.location?.coordinate.longitude ?? 0))" webView?.evaluateJavaScript(script) } } } }
index.html
<!DOCTYPE html> <html> <body> <h1>Click the button to get your coordinates.</h1> <button style="font-size: 60px;" onclick="getUserLocation()">Try It</button> <p id="demo"></p> <script> var x = document.getElementById("demo"); function getUserLocation() { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(showPosition); } else { x.innerHTML = "Geolocation is not supported by this browser."; } } function showPosition(position) { getLocation(position.coords.latitude,position.coords.longitude); } function getLocation(lat,lng) { x.innerHTML = "Lat: " + lat+ "<br>Lng: " + lng; } </script> </body> </html>
source share