Turns out it’s quite hard, but possible to do. You have to inject JavaScript code which intercepts requests to navigator.geolocation
and transfer them to your app, then get the location with CLLocationManager
, then inject location back to the JavaScript.
Here is the brief scheme:
-
Add
WKUserScript
to yourWKWebView
configuration which overrides methods ofnavigator.geolocation
. Injected JavaScript should look like this:navigator.geolocation.getCurrentPosition = function(success, error, options) { ... }; navigator.geolocation.watchPosition = function(success, error, options) { ... }; navigator.geolocation.clearWatch = function(id) { ... };
-
With
WKUserContentController.add(_:name:)
add script message handler to yourWKWebView
. Injected JavaScript should call your handler, like this:window.webkit.messageHandlers.locationHandler.postMessage('getCurrentPosition');
-
When a web page will request a location, this method will fire
userContentController(_:didReceive:)
so your app would know web page is requesting location. Find your location with the help ofCLLocationManager
as usual. -
Now it’s time to inject the location back to the requesting JavaScript with
webView.evaluateJavaScript("didUpdateLocation({coords: {latitude:55.0, longitude:0.0}, timestamp: 1494481126215.0})")
.
Of course your injected JavaScript should havedidUpdateLocation
function ready to launch saved success handler.
Quite a long algorithm, but it works!