UIWebView loads web content

You can use local files or urls.

NSString *htmlPath = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL fileURLWithPath:htmlPath]];
[self.webView loadRequest:request];
Copy the code

Native invoke JavaScript

Native calls JS are implemented by UIWebView stringByEvaluatingJavaScriptFromString method, this method returns the JS script execution results.

[webView stringByEvaluatingJavaScriptFromString:@"Math.random();"];
Copy the code

It’s actually calling an object under the Window of the page. If we want the native side to call the JS method, then the JS method must be accessible under the window.

JavaScript call Native

On the other hand, JavaScript calls Native, and there is no ready-made API to call, but indirectly through some other means. UIWebView has a proxy method: any network request made within UIWebView can be notified in the Native layer through the delegate function. With this in mind, we can make a custom network request in UIWebView, usually in the form jsbridge://methodName? param1=value1&param2=value2…

In UIWebView’s delegate function, we determine the scheme of the request. If request.url.scheme is jsBridge, then the web content is not loaded, but the corresponding method is executed. The method name is request.url.host. The parameters can be obtained from request.url.query.

The question is…?

There are two ways to initiate such a network request. 1:location.href.2: iframe. There is a problem with location.href. If js calls the Native method several times, that is, the value of location.href changes several times, the Native end can only accept the last request, and the previous request will be ignored.

Use ifrmae to call Native methods.

var iFrame;
iFrame = document.createElement("iframe");
iFrame.style.height = "1px";
iFrame.style.width = "1px";
iFrame.style.display = "none";
iFrame.src = url;
document.body.appendChild(iFrame);
setTimeout(function(){ iFrame.remove(); }, 100);Copy the code

An 🌰 :

Requirements:

The native side provides a UIWebView that loads a web page content. There is also a button to click on the page to add a paragraph of text. There are two input boxes on the web page. The user enters a number and clicks the button. Js tells the parameters entered by the user to the Native terminal, which performs addition and returns the result to JS after calculation

//index.html


<html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf8">
    <script language="javascript">
    function loadURL(url) {
        var iFrame;
        iFrame = document.createElement("iframe");
        iFrame.style.height = "1px";
        iFrame.style.width = "1px";
        iFrame.style.display = "none";
        iFrame.src = url;
        document.body.appendChild(iFrame);
        setTimeout(function() {
            iFrame.remove();
        }, 100);
    }


    function receiveValue(value) {
        alert("The result of addition from primitive is:" + value);
    }

    function check() {
        var par1 = document.getElementById("par1").value;
        var par2 = document.getElementById("par2").value;
        loadURL("JSBridge://plus? par1=" + par1 + "&par2=" + par2);
    }
    </script>
</head>

<body>
    <input type="text" placeholder="Please enter a number" id="par1"/ > + < inputtype="text" placeholder="Please enter a number" id="par2"/ > < inputtype="button" value="=" onclick="check()" />
</body>

</html>
Copy the code
//ViewController.m

-(void)addContentToWebView{
    NSString *jsString = @" var pNode = document.createElement(\"p\"); Pnode. innerText = \" I am adding a file to the HTML by calling javascript from native code, i.e. injecting \"; document.body.appendChild(pNode);";
    [self.webView stringByEvaluatingJavaScriptFromString:jsString];
}


-(NSInteger)plusparm:(NSInteger)par1 parm2:(NSInteger)par2{
    return par1 + par2;
}


#pragma mark -- UIWebViewDelegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
    NSURL *url = request.URL;
    NSString *scheme = url.scheme;
    NSString *method = url.host;
    NSString *parms =  url.query;
    NSArray *pars = [parms componentsSeparatedByString:@"&"];
    NSInteger par1 = [[pars[0] substringFromIndex:5] integerValue];
    NSInteger par2 = [[pars[1] substringFromIndex:5] integerValue];
    if ([scheme isEqualToString:@"jsbridge"] {// If scheme is JSBridge, then it is a custom URLscheme that does not load web content but intercepts events.if ([method isEqualToString:@"plus"]) {
            NSInteger result = [self plusparm:par1 parm2:par2];
            [self.webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"receiveValue(%@);",@(result)]];
        }
        
        return NO;
    }
    return YES;
}

Copy the code

Synchronous and asynchronous issues

Native js calls is by inserting an iframe in a web page, insert the iframe is finished, the result of the execution need native call stringByEvaluatingJavaScriptString method to notify other js. This is obviously an asynchronous call. StringByEvaluatingJavaScriptString method returns and carry out a js script. Essentially a synchronous call

So JS call native is asynchronous, native call JS is synchronous.