標籤:是什麼 red nullable form js調用 rem array run content
在開發過程中,經常會出現需要iOS移動端與H5混編的使用情境。 iOS中載入html網頁, 可以使用UIWebView或WKWebView. 本篇部落格將介紹兩種控制項使用過程中如何?OC與JS的互動。
UIWebView delegate 協議方法 //網頁即將開始載入 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType; //網頁開始載入 - (void)webViewDidStartLoad:(UIWebView *)webView; //網頁載入完成 - (void)webViewDidFinishLoad:(UIWebView *)webView; //網頁載入失敗 - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error; //UIWebView內建了一個方法, 可以直接調用JS代碼(轉化為string類型的js代碼) - (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script; //例如修改id為‘html’標籤內部的text屬性 [web stringByEvaluatingJavaScriptFromString:@"document.getElementById(‘html‘).innerText=‘修改內容‘"]; //也可以執行多行js代碼 [web stringByEvaluatingJavaScriptFromString:@"var div = document.getElementById(‘html‘); div.innerText = ‘修改內容‘"];
利用JavaScriptCore實現互動
JavaScriptCore中類及協議:
JSContext:給JavaScript提供啟動並執行上下文環境 JSValue:JavaScript和Objective-C資料和方法的橋樑 JSManagedValue:管理資料和方法的類 JSVirtualMachine:處理線程相關,使用較少 JSExport:這是一個協議,如果採用協議的方法互動,自己定義的協議必須遵守此協議
OC中提供了JavaScriptCore 這個庫,使得OC與js的互動變得更加方便。 使用方法: 1 加入JavaScriptCore 這個framework 2 引入標頭檔<JavaScriptCore/JavaScriptCore.h> 3 在VC裡面加入一個JSContext屬性 @property (strong, nonatomic) JSContext *context; JSContext是什麼那? 我們看一下api裡面的解釋
@interface @discussion A JSContext is a JavaScript execution environment. All JavaScript execution takes place within a context, and all JavaScript values are tied to a context.
大概意思是說:JSContext是一個JS的執行環境,所有的JS執行都發生在一個context裡面, 所有的JS value都綁定到context裡面具體使用
//初始化context self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; //OC調用JS //(1)例如html的script中一個方法 function dolike(a,b,c){ } //通過OC調用此方法 NSString * method = @"dolike"; JSValue * function = [self.context objectForKeyedSubscript:method]; //這裡面的a,b,c就是OC調用JS的時候給JS傳的參數 [function callWithArguments:@[a,b,c]]; //JS調用OC //例如網頁中有個標籤,點擊button的時候調用Jump方法, 此處3為傳入的參數 <button onclick="jump(‘3‘)">點我</button> //當點擊網頁中的button的時候,觸發jump方法, 在OC中用如下代碼可以捕捉到jump方法, 並拿到JS給我傳的參數‘3’ self.context[@"jump"] = ^(NSString * str){ //此處 str 值為‘3‘(js調用OC時傳給OC的參數) };
WKWebView :
說到WKWebView, 首先要說下WKWebView的優勢
1 更多的支援HTML5的特性
2 官方宣稱的高達60fps的滾動重新整理率以及內建手勢
3 將UIWebViewDelegate與UIWebView拆分成了14類與3個協議,以前很多不方便實現 的功能得以實現
4 Safari相同的JavaScript引擎
5 佔用更少的記憶體
類:
WKBackForwardList: 之前訪問過的 web 頁面的列表,可以通過後退和前進動作來訪問到。 WKBackForwardListItem: webview 中後退列表裡的某一個網頁。 WKFrameInfo: 包含一個網頁的布局資訊。 WKNavigation: 包含一個網頁的載入進度資訊。 WKNavigationAction: 包含可能讓網頁導航變化的資訊,用於判斷是否做出導航變化。 WKNavigationResponse: 包含可能讓網頁導航變化的返回內容資訊,用於判斷是否做出導航變化。 WKPreferences: 概括一個 webview 的喜好設定。 WKProcessPool: 表示一個 web 內容載入池。 WKUserContentController: 提供使用 JavaScript post 資訊和注射 script 的方法。 WKScriptMessage: 包含網頁發出的資訊。 WKUserScript: 表示可以被網頁接受的使用者指令碼。 WKWebViewConfiguration: 初始化 webview 的設定。 WKWindowFeatures: 指定載入新網頁時的視窗屬性。
協議:
WKNavigationDelegate: 提供了追蹤主視窗網頁載入過程和判斷主視窗和子視窗是否進行頁面載入新頁面的相關方法。 WKScriptMessageHandler: 提供從網頁中收訊息的回調方法。 WKUIDelegate: 提供用原生控制項顯示網頁的方法回調。
載入方式: //方式一 WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds]; [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]]]; [self.view addSubview:webView]; //方式二 WKWebViewConfiguration * configuration = [[WKWebViewConfiguration alloc] init]; webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:configuration]; [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]]]; [self.view addSubview:webView];協議方法介紹: #pragma mark - WKNavigationDelegate // 頁面開始載入時調用 - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{ } // 當內容開始返回時調用 - (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{ } // 頁面載入完成之後調用 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{ } // 頁面載入失敗時調用 - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation{ } // 接收到伺服器跳轉請求之後調用 - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation{ } // 在收到響應後,決定是否跳轉 - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{ NSLog(@"%@",navigationResponse.response.URL.absoluteString); //允許跳轉 decisionHandler(WKNavigationResponsePolicyAllow); //不允許跳轉 //decisionHandler(WKNavigationResponsePolicyCancel); } // 在發送請求之前,決定是否跳轉 - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{ NSLog(@"%@",navigationAction.request.URL.absoluteString); //允許跳轉 decisionHandler(WKNavigationActionPolicyAllow); //不允許跳轉 decisionHandler(WKNavigationActionPolicyCancel); } #pragma mark - WKUIDelegate // 建立一個新的WebView - (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{ return [[WKWebView alloc]init]; } // 輸入框 - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler{ completionHandler(@"http"); } // 確認框 - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler{ completionHandler(YES); } // 警告框 - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{ NSLog(@"%@",message); completionHandler(); }
OC與JS的互動
WKWebView
WKWebView的 UIDelegate 提供了三個協議方法, 可以讓前端很方便的攔截JS的alert, confirm, prompt方法。除此之外,OC,JS互調可以按照如下方法。
1 OC 調用JS
可以使用webkit這個庫
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;//例如OC調用JS的方法 setName [webView evaluateJavaScript:@"setname(‘張三‘)" completionHandler:nil];//此處 setname為JS定義的方法名, 內部 ‘張三’為傳給JS的參數。 如果setname方法需要傳入一個json或者array等非字元參數, 需要用format方法將其轉為string類型,在調用evaluate方法。例如 NSString * para = [NSString stringWithFormat:@"setname(‘%@‘)",json];
JS調用OC
此時就要用到WKScriptMessageHandler了
//首先.m中加入屬性 @property (nonatomic ,strong)WKUserContentController * userCC;//1 遵循WKScriptMessageHandler協議//2 初始化 WKWebViewConfiguration * config = [[WKWebViewConfiguration alloc]init]; self.wkWebViw = [[WKWebView alloc]initWithFrame:self.view.bounds configuration:config]; [self.wkWebViw loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.webPageUrl]]]; [self.view addSubview:self.wkWebViw]; self.userCC = config.userContentController; [self.userCC addScriptMessageHandler:self name:@"callOSX"]; //此處相當於監聽了JS中callFunction這個方法 [self.userCC addScriptMessageHandler:self name:@"callFunction"]; //當JS發出callFunction這個方法指令的時候, WKScriptMessageHandler的協議方法中我們就會收到這個訊息 #pragma mark WKScriptMessageHandler delegate - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {//這個回調裡面, message.name代表方法名(‘本例為 callFunction’), message.body代表JS給我們傳過來的參數 }//最後, VC銷毀的時候一定要把handler移除-(void)dealloc{ [_userContentController removeScriptMessageHandlerForName:@"callFunction"];}//對應的JS代碼<button onclick="buttonClick(‘溫馨提示‘)">點我</button><script> function buttonClick(string){ //JS調用OC, 格式如下 //(window.webkit.messageHandlers.Method_Name.postMessage(parameterToOC)) window.webkit.messageHandlers.callFunction.postMessage(string) } </script>
OC與JS的互動(iOS與H5混編)