iOS交互-JavaScriptCore

iOS交互一般有兩個(gè)選擇

  • JavaScriptCore
  • OC調(diào)用JavaScript通過(guò)webview的stringByEvaluatingJavaScriptFromString:方法調(diào)用JavaScript代碼;JavaScript調(diào)用OC,則是通過(guò)web view的代理方法shouldStartLoadWithRequest:來(lái)接收J(rèn)avaScript的網(wǎng)絡(luò)請(qǐng)求從而實(shí)現(xiàn)調(diào)用,推薦Marcus Westin的開源框架 WebViewJavascriptBridge。

在ios7之后,蘋果開放了JavaScriptCore,讓Objective-C和JavaScript代碼直接的交互變得更加的簡(jiǎn)單方便。這里就說(shuō)說(shuō)如何使用JavaScriptCore進(jìn)行交互。

iOS開發(fā)使用JavaScriptCore進(jìn)行交互有兩種方式:遵循JSExport協(xié)議,使用block。對(duì)JavaScriptCore不熟悉的看這篇挺不錯(cuò)的iOS7新JavaScriptCore框架入門介紹

先設(shè)定一個(gè)交互的使用需求背景:
假如有這樣一個(gè)需求:點(diǎn)擊網(wǎng)頁(yè)上的按鈕,調(diào)用本地代碼,然后本地代碼調(diào)用網(wǎng)頁(yè)js的方法改變按鈕樣式,點(diǎn)擊這里看動(dòng)圖展示

oc端

  • 導(dǎo)入JavaScriptCore
    #import <JavaScriptCore/JavaScriptCore.h>

  • JSExport方式:
    繼承JSExport協(xié)議, 在協(xié)議中定義自己的方法,在需要交互的ViewController遵循此協(xié)議并實(shí)現(xiàn)協(xié)議中的方法。該協(xié)議的方法會(huì)暴露給js調(diào)用,也就是網(wǎng)頁(yè)所調(diào)用本地的方法就是協(xié)議中的方法。
    下面定義一繼承至JSExport的協(xié)議,名為jsObjDelegate的協(xié)議

@protocol jsObjDelegate <JSExport>
-(void)test:(NSString *)str;
@end

創(chuàng)建一個(gè)類,包含兩個(gè)個(gè)屬性。一個(gè)是加載網(wǎng)頁(yè)的webView,另一個(gè)是js的運(yùn)行環(huán)境JSContext

@interface webViewController ()<jsObjDelegate,UIAlertViewDelegate,UIWebViewDelegate>{
    UIWebView * _webView;
    JSContext * _jsContext;
}

實(shí)現(xiàn)協(xié)議中的方法

-(void)test:(NSString *)str{
    UIAlertView * al = [[UIAlertView alloc]initWithTitle:@"網(wǎng)頁(yè)成功調(diào)用OC!" message:str delegate:self cancelButtonTitle:@"yes" otherButtonTitles:@"no", nil];
    al.tag = 3001;
    [al show];
}

在viewDidLoad里面vebView加載本地html

    NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"two.html" withExtension:nil];
    NSURLRequest *request = [NSURLRequest requestWithURL:fileURL];
    [_webView loadRequest:request];

在vebView加載完成后,獲取網(wǎng)頁(yè)的javaScriptContext屬性并保存到_jsContext中,把當(dāng)前控制器保存到網(wǎng)頁(yè)的javaScriptContext中,名為“ ctrl”,至此網(wǎng)頁(yè)用"ctrl"這個(gè)對(duì)象就能直接調(diào)用到協(xié)議中的test方法

-(void)webViewDidFinishLoad:(UIWebView *)webView{
    _jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
     //把當(dāng)前控制器保存到網(wǎng)頁(yè)中
    _jsContext[@"ctrl"] = self;
    _jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) {
        context.exception = exceptionValue;
        NSLog(@"異常信息:%@", exceptionValue);
    };
}

網(wǎng)頁(yè)調(diào)用協(xié)議中暴露的test方法
ctrl.test("方式:直接調(diào)用 \n是否回調(diào)網(wǎng)頁(yè)方法")

  • Block方式
    block方式viewController無(wú)需實(shí)現(xiàn)jsObjDelegate協(xié)議,在加載網(wǎng)頁(yè)完成時(shí)候 向網(wǎng)頁(yè)中的javaScriptContext注入方法即可。這里注入的方法名為“test2” 。在網(wǎng)頁(yè)中JS直接調(diào)用test2就能進(jìn)入block里面調(diào)用co代碼
-(void)webViewDidFinishLoad:(UIWebView *)webView{
    _jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    _jsContext[@"ctrl"] = self;
    _jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) {
        context.exception = exceptionValue;
        NSLog(@"異常信息:%@", exceptionValue);
    };
    WS(weakSelf);
    _jsContext[@"test2"]=^(NSString * string){
//        NSArray * arr = [JSContext currentArguments ];
//        JSValue * value = arr[0];
//        NSString * str = [value toString];
//        thread = [NSThread currentThread];
        UIAlertView * al = [[UIAlertView alloc]initWithTitle:@"網(wǎng)頁(yè)成功調(diào)用OC!" message:string delegate:weakSelf cancelButtonTitle:@"yes" otherButtonTitles:@"no", nil];
        al.tag = 3000;
        [al show];
    };
}

網(wǎng)頁(yè)調(diào)用oc中注入的test2方法
test2("方式:block \n是否回調(diào)網(wǎng)頁(yè)方法")

oc調(diào)用網(wǎng)頁(yè)的方法,向js的同一個(gè)方法傳入不同的參數(shù)

-(void)callback{
    JSValue * callback = _jsContext[@"showMessage"];
    [callback callWithArguments:@[@"oc調(diào)用html方法 \n是否改變第一個(gè)按鈕的背景顏色",@(1)]];
}
-(void)callback2{
    JSValue * callback = _jsContext[@"showMessage"];
    [callback callWithArguments:@[@"oc調(diào)用html方法  \n是否改變第二個(gè)按鈕的背景顏色",@(2)]];
}

網(wǎng)頁(yè)端

這里是完整的js代碼,通過(guò)jsObjDelegate協(xié)議和block方式調(diào)用本地代碼的調(diào)用方式都在這里。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>iOS與js的交互</title>
<script src="http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js"></script>
</head>
<body>
<h1>iOS與js的交互</hi><br>
<div>
<input  id="btn1" type="button" value="JSExport協(xié)議調(diào)用oc代碼"/><br>
<input  id="btn2" type="button" value="Block調(diào)用oc代碼"/>
</div>
<script type="text/javascript">
$(function(){
    $("#btn1").bind("click", function(){
        //給btn1綁定事件,ctrl是上面保存的控制器。這里直接調(diào)用 jsObjDelegate暴露出來(lái)方法
        ctrl.test("方式:直接調(diào)用 \n是否回調(diào)網(wǎng)頁(yè)方法")
    }); 
    $("#btn2").bind("click",function(){
      //btn2綁定事件,這里直接調(diào)用oc中以block方式注入的方法
        test2("方式:block \n是否回調(diào)網(wǎng)頁(yè)方法")});
})
//根據(jù)index的值修改按鈕的樣式。oc代碼會(huì)調(diào)用該方法
function showMessage(str,index){
    if(index == 1 && confirm(str)){
        $("#btn1").css("background-color","red");
        return;
    }  
    if(confirm(str)){
        $("#btn2").css("background-color","green");
    }
}
</script>
</body>
</html>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 跟原生開發(fā)相比,H5的開發(fā)相對(duì)來(lái)一個(gè)成熟的框架和團(tuán)隊(duì)來(lái)講在開發(fā)速度和開發(fā)效率上有著比原生很大的優(yōu)勢(shì),至少不用等待審...
    大沖哥閱讀 1,904評(píng)論 0 7
  • 隨著H5技術(shù)的興起,在iOS開發(fā)過(guò)程中,難免會(huì)遇到原生應(yīng)用需要和H5頁(yè)面交互的問(wèn)題。其中會(huì)涉及方法調(diào)用及參數(shù)傳值等...
    Chris_js閱讀 3,245評(píng)論 1 8
  • JavaScriptCore框架主要是用來(lái)實(shí)現(xiàn)iOS與H5的交互。由于現(xiàn)在混合編程越來(lái)越多,H5的相對(duì)講多,所以研...
    水靈芳蕥閱讀 1,500評(píng)論 1 8
  • 我叫常征。 我是一個(gè)旅行作家。 今天是我28歲這一年的倒數(shù)第63天。 此刻,我跟隨這趟叫G158的高鐵,從滄州西開...
    冰城筆記閱讀 333評(píng)論 0 1
  • 如果早知道不能考上理想的大學(xué),還會(huì)挑燈夜戰(zhàn)看書刷題到凌晨嗎? 如果早知道大學(xué)畢業(yè)后沒(méi)能力沒(méi)背景找不到好工作,還會(huì)天...
    lcgaga閱讀 251評(píng)論 0 1

友情鏈接更多精彩內(nèi)容