iOS與JS交互之UIWebView-JavaScriptCore框架

級別:★★☆☆☆
標籤:「iOS與JS交互」「UIWebView與JS交互」「JavaScriptCore」
做者: Xs·H
審校: QiShare團隊php

先解釋下標題:「iOS與JS交互」。iOS指iOS原生代碼(文章只有OC示例),JS指WEB前端(不單指JavaScript),交互指JS調用iOSiOS調用JS。 做者將iOS與JS交互總結成了6種方式,並將逐一介紹。目錄以下:前端


本文介紹如何使用JavaScriptCore框架在 UIWebView上實現iOSJS交互。 JavaScriptCoreAppleiOS7開放的框架。它爲在UITableView上實現OCJS的交互提供了更爲簡單的方式。vue

1、JS調用iOS:
  • 實現邏輯:點擊JS的登陸按鈕,JS將登陸成功後的token數據傳遞給iOS,iOS將收到的數據展現出來。
  • 實現效果:
    JS調用iOS實現效果
  • JS代碼:
//! 登陸按鈕
<button onclick = "login()" style = "font-size: 18px;">登陸</button>
複製代碼
//! 登陸
function login() {
  var token = "js_tokenString";
  loginSucceed(token);
}

//! 登陸成功
function loginSucceed(token) {
  var action = "loginSucceed";
  jsToOc(action, token);
}

//! JS調用OC入口
function jsToOc(action, params) {
  var url = "jsToOc://" + action + "?" + params;
  loadURL(url);
}

//! 加載URL
function loadURL(url) {
  window.location.href = url;
}
複製代碼
  • iOS代碼:
//! 導入JavaScriptCore框架頭文件
#import <JavaScriptCore/JavaScriptCore.h>
複製代碼
#pragma mark - UIWebViewDelegate

//! UIWebView在每次加載請求完成後會調用此方法
- (void)webViewDidFinishLoad:(UIWebView *)webView {
    
    //! 獲取JS代碼的執行環境/上下文/做用域
    JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

    //! 監聽JS代碼裏面的jsToOc方法(執行效果上能夠理解成重寫了JS的jsToOc方法)
    context[@"jsToOc"] = ^(NSString *action, NSString *params) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [UIWebViewJavaScriptCoreController showAlertWithTitle:action message:params cancelHandler:nil];
        });
    };
}
複製代碼
  • 實現原理: 一、JS與iOS約定好jsToOc方法,做爲JS調用iOS的入口;
    二、iOS經過[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]獲取JS代碼的上下文JSContext;
    三、JS調用jsToOc方法,iOS使用Block形式監聽(重寫)此方法context[@"jsToOc"] = ^() {},收到JS的調用請求和參數;

PS:在使用Block形式監聽(重寫)JS的方法的時候,不要在Block中直接使用外部的JSValueJSContent,由於JSContext強引用BlockBlock強引用外部變量,JSValue又強引用JSContextJSValue須要JSContext來執行JS代碼),會造成循環引用。由於JS沒有弱引用的概念,因此__weak不會奏效,能夠經過將JSValue做爲Block內部參數和[JSContext currentContext]的方式分別解決兩類循環引用的問題。java


2、iOS調用JS:
  • 實現邏輯:點擊iOS的登陸按鈕,iOS將登陸成功後的token數據傳遞給JS,JS將收到的數據展現出來。git

  • 實現效果: github

    iOS調用JS實現效果

  • iOS代碼:web

//! 登陸按鈕
UIBarButtonItem *loginBtnItem = [[UIBarButtonItem alloc] initWithTitle:@"登陸" style:UIBarButtonItemStylePlain target:self action:@selector(login:)];
self.navigationItem.rightBarButtonItems = @[loginBtnItem];
複製代碼
//! 登陸方法
- (void)login:(id)sender {
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
        //! JSContext -evaluateScript:方式調用JS方法
        [context evaluateScript:[NSString stringWithFormat:@"ocToJs('loginSucceed', 'oc_tokenString')"]];
        //! JSValue -callWithArguments:方式調用JS方法
        // [context[@"ocToJs"] callWithArguments:@[@"loginSucceed", @"oc_tokenString"]];
    });
}
複製代碼
  • JS代碼:
//! iOS調用JS入口
function ocToJs(action, params) {
  document.getElementById("returnValue").innerHTML = action + '?' + params;
}
複製代碼
//! iOS調用JS數據顯示框
<div id = "returnValue" style = "font-size: 18px; border: 1px dotted; height: 50px;"> </div>
複製代碼
  • 實現原理: 一、iOS經過UITableView的-valueForKeyPath:方法獲取JSContext對象(保證在最新的JS環境中執行JS代碼);
    二、iOS經過JSContext的-evaluateScript:方法執行一段JS代碼ocToJs('loginSucceed', 'oc_tokenString')
    三、JS在ocToJs方法中將iOS傳過來的數據顯示在div元素中。

PS:除了使用JSContext的-evaluateScript:方法以外,還能夠先經過[context[@"ocToJs"]獲取到JS的ocToJs方法對應的JSValue,而後使用JSValue的-callWithArguments:方法調用JS的ocToJs方法。vue-cli


續篇:iOS與JS交互之UIWebView-JSExport協議(明天更新)
bash


關注咱們的途徑有:
QiShare(簡書)
QiShare(掘金)
QiShare(知乎)
QiShare(GitHub)
QiShare(CocoaChina)
QiShare(StackOverflow)
QiShare(微信公衆號)微信

推薦文章:
vue-cli 自動化測試 Nightwatch 詳解
Vuex工做原理詳解

相關文章
相關標籤/搜索