EDIT: the solution was to return NO from the delegate method webView:shouldStartLoadWithRequest:navigationType:when it received a JavaScript message, this allowed everything in all versions.
JavaScript behavior on native (Obj-C or Swift) communication inside UIWebViewhas changed in iOS 8.3.
Let's say I want to send a couple of messages from JS to native code 1 :
window.open('myurlscheme://webview?message=1');
window.open('myurlscheme://webview?message=2');
window.open('myurlscheme://webview?message=3');
window.open('myurlscheme://webview?message=4');
I use this delegate method to catch messages in native code:
- (BOOL)webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType {
if ([inRequest.URL.scheme isEqualToString:@"myurlscheme"]) {
NSLog(@"%@", inRequest.URL.absoluteString);
}
return YES;
}
And I get the following in the Xcode console:
15:19:56.387 TestJSObjCComms[55731:766108] myurlscheme:
15:19:56.404 TestJSObjCComms[55731:766108] myurlscheme:
16:20:06.300 TestJSObjCComms[57967:819448] void SendDelegateMessage(NSInvocation *): delegate (webView:decidePolicyForNavigationAction:request:frame:decisionListener:) failed to return after waiting 10 seconds. main run loop mode: kCFRunLoopDefaultMode
15:20:06.407 TestJSObjCComms[55731:766108] myurlscheme:
15:20:16.409 TestJSObjCComms[55731:766108] myurlscheme:
15:20:26.411 TestJSObjCComms[55731:766108] myurlscheme:
. , 10 . 30 , , ! , ( ) 10 , .
, UIWebView iOS 8.3, . , UIWebView JavaScript 10 . , JavaScript - , , .
, , , window.open(myURL) , window.location = myURL, , , , , .
1 window.open(myURL) window.location = myURL, (. 1 ).
1
. setTimeout "". , 3 iOS 8.3, 8.1 7.0, setTimeout 50 .
var buffer = [];
function doRequest(url) {
buffer.push(url);
if (buffer.length === 1) {
window.location = url;
}
}
function resolveRequest(request) {
var index = buffer.indexOf(request);
if (index != -1) {
buffer.splice(index, 1);
}
if (buffer.length) {
setTimeout(function() {
window.location = buffer[0];
}, 50);
}
}
, . - .
1: UIWebView JavaScript ↔ .
-
1) window.location = myURL ( window.location.href = myURL, window.location.replace(myURL) ..).
2) window.open(myURL) window.open(myURL, ‘_blank’) src: <iframe>, <embed>. , : <audio>, <video>, <script>, <style>.
3) , . , UIWebView webView:shouldStartLoadWithRequest:navigationType:.
JavaScript:
var buffer = [];
function doRequest(url) {
buffer.push(url);
if (buffer.length === 1) {
window.location = url;
}
}
function resolveRequest(request) {
var index = buffer.indexOf(request);
if (index != -1) {
buffer.splice(index, 1);
}
if (buffer.length) {
window.location = buffer[0];
}
}
Obj-C:
- (BOOL)webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType {
if ([inRequest.URL.scheme isEqualToString:@"myurlscheme"]) {
NSString *javaScript = [NSString stringWithFormat:@"resolveRequest('%@')", inRequest.URL.absoluteString];
[self.webView stringByEvaluatingJavaScriptFromString:javaScript];
NSLog(@"%@", inRequest.URL.absoluteString);
}
return YES;
}
( iPhone 5 Simulator)
iOS 7.1
1: .
2: ( ).
3: ( ).
iOS 8.1
1: , iOS 7.1
2: , 10 ( , ).
3: , iOS 7.1
iOS 8.3
1: , iOS 7.1
2: , iOS 8.1
3: , 10 ( , ).