1. UIWebView
UIWebView 適用於iOS8.0以下的系統版本 iOS原生沒有提供js直接呼叫OC的方式,只能通過UIWebView的UIWebViewDelegate協議方法來做攔截,並在這個方法中,根據url來呼叫OC方法;
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
複製程式碼
- UIWebViewDelegate代理協議使用:
// 是否允許載入網頁,也可獲取js要開啟的url,通過擷取此url可與js互動
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSString *urlString = [[request URL] absoluteString];
urlString = [urlString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSArray *urlComps = [urlString componentsSeparatedByString:@"://"];
NSLog(@"urlString=%@---urlComps=%@",urlString,urlComps);
return YES;
}
// 開始載入網頁
- (void)webViewDidStartLoad:(UIWebView *)webView {
NSURLRequest *request = webView.request;
NSLog(@"webViewDidStartLoad-url=%@--%@",[request URL],[request HTTPBody]);
}
// 網頁載入完成
- (void)webViewDidFinishLoad:(UIWebView *)webView {
NSURLRequest *request = webView.request;
NSURL *url = [request URL];
if ([url.path isEqualToString:@"/normal.html"]) {
NSLog(@"isEqualToString");
}
NSLog(@"webViewDidFinishLoad-url=%@--%@",[request URL],[request HTTPBody]);
NSLog(@"%@",[self.webView stringByEvaluatingJavaScriptFromString:@"document.title"]);
}
// 網頁載入錯誤
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
NSURLRequest *request = webView.request;
NSLog(@"didFailLoadWithError-url=%@--%@",[request URL],[request HTTPBody]);
}
複製程式碼
2. WKWebView
- 引入WebKit庫
#import <WebKit/WebKit.h>
- 在文件中可以看出,WKWebView的初始化方法有兩種:
- (instancetype)initWithFrame:(CGRect)frame
- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration
複製程式碼
我們大多使用第一種方式,這也是文件中預設的一種方式。
- WKWebView 代理 協議方法如下:
//頁面開始載入時呼叫
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation
{
NSLog(@"頁面開始載入時呼叫。 2");
}
//內容返回時呼叫,得到請求內容時呼叫(內容開始載入) -> view的過渡動畫可在此方法中載入
- (void)webView:(WKWebView *)webView didCommitNavigation:( WKNavigation *)navigation
{
NSLog(@"內容返回時呼叫,得到請求內容時呼叫。 4");
}
//頁面載入完成時呼叫
- (void)webView:(WKWebView *)webView didFinishNavigation:( WKNavigation *)navigation
{
NSLog(@"頁面載入完成時呼叫。 5");
}
//請求失敗時呼叫
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error
{
NSLog(@"error1:%@",error);
}
-(void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error
{
NSLog(@"error2:%@",error);
}
//在請求傳送之前,決定是否跳轉 -> 該方法如果不實現,系統預設跳轉。如果實現該方法,則需要設定允許跳轉,不設定則報錯。
//該方法執行在載入介面之前
//Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Completion handler passed to -[ViewController webView:decidePolicyForNavigationAction:decisionHandler:] was not called'
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
//允許跳轉
decisionHandler(WKNavigationActionPolicyAllow);
//不允許跳轉
// decisionHandler(WKNavigationActionPolicyCancel);
NSLog(@"在請求傳送之前,決定是否跳轉。 1");
}
//在收到響應後,決定是否跳轉(同上)
//該方法執行在內容返回之前
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
{
//允許跳轉
decisionHandler(WKNavigationResponsePolicyAllow);
//不允許跳轉
// decisionHandler(WKNavigationResponsePolicyCancel);
NSLog(@"在收到響應後,決定是否跳轉。 3");
}
//接收到伺服器跳轉請求之後呼叫
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation
{
NSLog(@"接收到伺服器跳轉請求之後呼叫");
}
-(void)webViewWebContentProcessDidTerminate:(WKWebView *)webView
{
NSLog(@"webViewWebContentProcessDidTerminate");
}
複製程式碼
3. OC呼叫JS傳遞引數
- UIWebView方法
NSString *str = [self.webview stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"postStr('%@','%@');",str1,str2]];
複製程式碼
- WKWebView方法
[self.wkWebView evaluateJavaScript:[NSString stringWithFormat:@"postStr('%@')", @"true"] completionHandler:^(id _Nullable result, NSError * _Nullable error) {
NSLog(@"==%@----%@", result, error);
}];
複製程式碼
在需要接受引數值的js介面實現如下方法:
function postStr(str1, str2){
alert(str1, str2); //接收到的值”;
//...code
}
複製程式碼
4. JS呼叫OC傳遞引數
js是不能執行oc程式碼的,但是可以變相的執行,js可以將要執行的操作封裝到網路請求裡面,然後oc攔截這個請求,獲取url裡面的字串解析即可。(攔截URL)
比如darkangel://。方法是在html或者js中,點選某個按鈕觸發事件時,跳轉到自定義URL Scheme構成的連結,而OC中捕獲該連結,從中解析必要的引數,實現JS到OC的一次互動。比如頁面中一個a標籤,連結如下:
<a href="darkangel: smslogin?username="12323123&code=892845"">簡訊驗證登入</a href="darkangel:>
在該方法中,捕獲該連結,並且返回NO(阻止本次跳轉),從而執行對應的OC方法。
- UIWebView方法
/*
* 方法的返回值是BOOL值。
* 返回YES:表示讓瀏覽器執行預設操作,比如某個a連結跳轉
* 返回NO:表示不執行瀏覽器的預設操作,這裡因為通過url協議來判斷js執行native的操作,肯定不是瀏覽器預設操作,故返回NO
*/
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
//標準的URL包含scheme、host、port、path、query、fragment等
NSURL *URL = request.URL;
if ([URL.scheme isEqualToString:@"darkangel"]) {
if ([URL.host isEqualToString:@"smsLogin"]) {
NSLog(@"簡訊驗證碼登入,引數為 %@", URL.query);
return NO;
}
}
return YES;
}
複製程式碼
- WKWebView方法
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
//可以通過navigationAction.navigationType獲取跳轉型別,如新連結、後退等
NSURL *URL = navigationAction.request.URL;
//判斷URL是否符合自定義的URL Scheme
if ([URL.scheme isEqualToString:@"darkangel"]) {
//根據不同的業務,來執行對應的操作,且獲取引數
if ([URL.host isEqualToString:@"smsLogin"]) {
NSString *param = URL.query;
NSLog(@"簡訊驗證碼登入, 引數為%@", param);
//不允許跳轉
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
}
//允許跳轉
decisionHandler(WKNavigationActionPolicyAllow);
NSLog(@"%@", NSStringFromSelector(_cmd));
}
複製程式碼