能夠經過本地文件、url等方式。javascript
NSString *htmlPath = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"]; NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL fileURLWithPath:htmlPath]]; [self.webView loadRequest:request];
Native調用JS是經過UIWebView的stringByEvaluatingJavaScriptFromString 方法實現的,該方法返回js腳本的執行結果。html
[webView stringByEvaluatingJavaScriptFromString:@"Math.random();"];
實際上就是調用了網頁的Window下的一個對象。若是咱們須要讓native端調用js方法,那麼這個js方法必須在window下能夠訪問到。java
反過來,JavaScript調用Native,並無現成的API能夠調用,而是間接地經過一些其它手段來實現。UIWebView有個代理方法:在UIWebView內發起的任何網絡請求均可以經過delegate函數在Native層獲得通知。由此思路,咱們就能夠在UIWebView內發起一個自定義的網絡請求,一般是這樣的格式:jsbridge://methodName?param1=value1¶m2=value2...web
在UIWebView的delegate函數中,咱們判斷請求的scheme,若是request.URL.scheme是jsbridge,那麼就不進行網頁內容的加載,而是去執行相應的方法。方法名稱就是request.URL.host。參數能夠經過request.URL.query獲得。網絡
問題來了??app
發起這樣1個網絡請求有2種方式。1:location.href .2:iframe。經過location.href有個問題,就是若是js屢次調用原生的方法也就是location.href的值屢次變化,Native端只能接受到最後一次請求,前面的請求會被忽略掉。dom
使用ifrmae方式,以調用Native端的方法。異步
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);
舉個🌰:函數
需求:ui
原生端提供一個UIWebView,加載一個網頁內容。還有1個按鈕,按鈕點擊一下網頁增長一段段落文本。網頁上有2個輸入框,用戶輸入數字,點擊按鈕,js將用戶輸入的參數告訴native端,native去執行加法,計算完成後將結果返回給js
//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("從原生拿到加法結果爲:"+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="請輸入數字" id="par1"/> + <input type="text" placeholder="請輸入數字" id="par2"/> <input type="button" value="=" onclick="check()" /> </body> </html> //ViewController.m -(void)addContentToWebView{ NSString *jsString = @" var pNode = document.createElement(\"p\"); pNode.innerText = \"我是由原生代碼調用js後將一段文件添加到html上,也就是注入\";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"]) { //發現scheme是JSBridge,那麼就是自定義的URLscheme,不去加載網頁內容而攔截去處理事件。 if ([method isEqualToString:@"plus"]) { NSInteger result = [self plusparm:par1 parm2:par2]; [self.webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"receiveValue(%@);",@(result)]]; } return NO; } return YES; }
js調用native是經過在一個網頁上插入一個iframe,這個iframe插入完了就完了,執行的結果須要native另外調用stringByEvaluatingJavaScriptString 方法通知js。這明顯是1個異步的調用。而stringByEvaluatingJavaScriptString方法會返回執行js腳本的結果。本質上是一個同步調用
因此js call native是異步,native call js是同步。