iOS - WebKit與JS的簡單交互

直接上代碼

JS調(diào)OC

OC中的實現(xiàn)

1.創(chuàng)建一個WKWebViewConfiguration

 WKWebViewConfiguration 是用來配置WKWebView的
 WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
 configuration.userContentController = [WKUserContentController new];
  // 注冊一個處理事件 參數(shù)1:誰來響應(yīng)這個操作事件(類似于代理恕刘,遵守 WKScriptMessageHandler 協(xié)議)  參數(shù)2: 操作唯一標(biāo)識符
  //[configuration.userContentController addScriptMessageHandler:self name:@"操作的唯一標(biāo)識"]; 
 [configuration.userContentController addScriptMessageHandler:self name:@"testAction"];   

2.創(chuàng)建一個WKWebView 與 WKWebViewConfiguration關(guān)聯(lián)起來

self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:configuration];  
self.webView.backgroundColor = [UIColor whiteColor];
[self.webView loadRequest:[NSURLRequest requestWithURL:@"........."]]; 
[self.view addSubview:self.webView];
  1. 實現(xiàn) WKScriptMessageHandler 協(xié)議中的 userContentController: didReceiveScriptMessage 方法來監(jiān)聽上述配置中的操作事件
#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
    NSLog(@"%@",message.name); // 注冊操作事件時的唯一標(biāo)示符
    NSLog(@"%@",message.body); // JS返回回來的數(shù)據(jù)
    // 判定name來決定是哪個操作事件
    if([message.name isEqualToString:@"testAction"]){
      NSLog(@"testAction")
    }
}

4.使用結(jié)束后 確定該標(biāo)識不需要用 需要刪除 要不然會強引用

[configuration.userContentController removeScriptMessageHandlerForName:@"testAction"];
Swift
let configuration = WKWebViewConfiguration()
configuration.userContentController = WKUserContentController()
configuration.userContentController.add(self, name: "testAction")
        
self.webView = WKWebView.init(frame: self.view.bounds, configuration: configuration)
self.view.addSubview(self.webView)
let url = URL(string: "----")!
self.webView.load(URLRequest(url: url))
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    print(message.name)
    print(message.body)        
 }
使用結(jié)束同樣需要刪除
configuration.userContentController.removeScriptMessageHandler(forName: "testAction")

同樣也是要遵守協(xié)議 WKScriptMessageHandler

JS中的實現(xiàn)
 在哪里需要調(diào)用OC 那么就在哪個函數(shù)中調(diào)用
 例:
  <script>
    function testAction() {
        <!--window.webkit.messageHandlers.方法名(與注冊的一致(message.name) ).postMessage(JS傳下來的數(shù)據(jù)(message.body))-->
      <!--data 可以是數(shù)組 字典 json字符串.....-->
        window.webkit.messageHandlers.testAction.postMessage(data)
    }
  </script>

OC調(diào)JS

OC中的實現(xiàn)
WKWebView中直接有方法可以調(diào)用
// 字符串內(nèi)容為:JS中的方法名(參數(shù)) 參數(shù)可以是數(shù)組 字典 json字符串
NSString *jsStr = [NSString stringWithFormat:@"showResult('10086')"];
[self.webView evaluateJavaScript:jsStr completionHandler:^(id _Nullable result, NSError * _Nullable error) {
    NSLog(@"%@----%@",result, error);
}];
Swift
let arr = ["1","2","3"]
let js = "showResult(\(arr))"
self.webView.evaluateJavaScript(js, completionHandler: { (result, error) in
    print(result ?? "nil",error ?? "nil")
})

completionHandler 會調(diào)中的 result 是js方法的返回值 (result是個 id / Any 類型,也就是說js中可以返回任意值)

JS中的實現(xiàn)
  <script>
    function showResult(result) {
      alert(result)
      return "hello,word"
    }
  </script>

其他

關(guān)于 JS中的alert彈框在WKWebView中無法彈出

原生的alert彈框在WK上面無法彈出
解決方法 :
1. 不使用原生的alert, 自定義一個彈框

2. 遵守WKUIDelegate 實現(xiàn)WKWebView的UIDelegate

// 顯示一個按鈕。點擊后調(diào)用completionHandler回調(diào)
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:message?:@"" preferredStyle:UIAlertControllerStyleAlert];
    [alertController addAction:([UIAlertAction actionWithTitle:@"確認(rèn)" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler();
    }])];
    [self presentViewController:alertController animated:YES completion:nil];
    
}

// 顯示兩個按鈕,通過completionHandler回調(diào)判斷用戶點擊的確定還是取消按鈕
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler{
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:message?:@"" preferredStyle:UIAlertControllerStyleAlert];
    [alertController addAction:([UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(NO);
    }])];
    [alertController addAction:([UIAlertAction actionWithTitle:@"確認(rèn)" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(YES);
    }])];
    [self presentViewController:alertController animated:YES completion:nil];
}

// 顯示一個帶有輸入框和一個確定按鈕的,通過completionHandler回調(diào)用戶輸入的內(nèi)容
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler{
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:prompt message:@"" preferredStyle:UIAlertControllerStyleAlert];
    [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
        textField.text = defaultText;
    }];
    [alertController addAction:([UIAlertAction actionWithTitle:@"完成" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(alertController.textFields[0].text?:@"");
    }])];
    
    [self presentViewController:alertController animated:YES completion:nil];
}

相當(dāng)于是系統(tǒng)在檢測到alert彈框時镐侯,會調(diào)用這些代理方法,然后通過代理方法把對應(yīng)參數(shù)告訴我們,我們自己實現(xiàn)alert方法來彈框

關(guān)于 JS中的select下拉框在WKWebView中的顯示樣式

js 中 select 下拉框在不同的瀏覽器顯示的樣式就不一樣拗军,在WKWebView中會已UIPickerView的形式展示,如果無法滿足需求蓄喇,需要自定義下拉框

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末发侵,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子妆偏,更是在濱河造成了極大的恐慌刃鳄,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钱骂,死亡現(xiàn)場離奇詭異叔锐,居然都是意外死亡,警方通過查閱死者的電腦和手機见秽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門愉烙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人解取,你說我怎么就攤上這事步责。” “怎么了肮蛹?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵勺择,是天一觀的道長。 經(jīng)常有香客問我伦忠,道長省核,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任昆码,我火速辦了婚禮气忠,結(jié)果婚禮上邻储,老公的妹妹穿的比我還像新娘。我一直安慰自己旧噪,他們只是感情好吨娜,可當(dāng)我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著淘钟,像睡著了一般宦赠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上米母,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天勾扭,我揣著相機與錄音,去河邊找鬼铁瞒。 笑死妙色,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的慧耍。 我是一名探鬼主播身辨,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼芍碧!你這毒婦竟也來了煌珊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤师枣,失蹤者是張志新(化名)和其女友劉穎怪瓶,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體践美,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡洗贰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了陨倡。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片敛滋。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖兴革,靈堂內(nèi)的尸體忽然破棺而出绎晃,到底是詐尸還是另有隱情,我是刑警寧澤杂曲,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布庶艾,位于F島的核電站,受9級特大地震影響擎勘,放射性物質(zhì)發(fā)生泄漏咱揍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一棚饵、第九天 我趴在偏房一處隱蔽的房頂上張望煤裙。 院中可真熱鬧掩完,春花似錦、人聲如沸硼砰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽题翰。三九已至恶阴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間遍愿,已是汗流浹背存淫。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留沼填,地道東北人。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓括授,卻偏偏與公主長得像坞笙,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子荚虚,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容