iOS JavaScriptCore實(shí)現(xiàn)OC與JS的交互

JS 與 OC 的交互原來(lái)沒(méi)有好好研究過(guò),用的都是比較簡(jiǎn)單攔截 Url 的方式,通過(guò)定義專(zhuān)用的 Url 來(lái)攔截關(guān)鍵字來(lái)進(jìn)行特定處理。但這只能用于簡(jiǎn)單的傳值,進(jìn)行一些簡(jiǎn)單的交互。涉及到,JS 調(diào)用 OC 方法或者 OC 調(diào)用 JS 方法,一些比較復(fù)雜的交互邏輯的時(shí)候這種方式就顯得力不從心了。滿(mǎn)足不了我們的需求。當(dāng)然也有比較好的第三方庫(kù)如:WebViewJavascriptBridge。但一般系統(tǒng)的方法足夠用的時(shí)候,就沒(méi)必要使用第三方庫(kù)。這樣即有利于減小安裝包體積,又可以減少第三方的不穩(wěn)定性等因素的干擾

一、攔截url的方式,進(jìn)行簡(jiǎn)單交互

在webView的代理方法中處理
  這里簡(jiǎn)單介紹一下 URL 里面的一些屬性
NSString *scheme = url.scheme;//協(xié)議:http
NSString *host = url.host;//主機(jī)名
NSNumber *port = url.port;//端口號(hào)
NSString *path = url.path;//一般用來(lái)表示主機(jī)上的一個(gè)目錄或文件地址
NSString *query = url.query;//參數(shù),發(fā)給服務(wù)器的參數(shù)

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
    NSURL *url = request.URL;
    if ([url.scheme isEqualToString:@"nanshanyi"]) {
        //在這里做JavaScript調(diào)用Objective-C的事。
        //需要傳的值放在url后面的參數(shù)里如:Nanshanyi://www.php8080.com?{"title":"標(biāo)題","id":"123","des":"描述內(nèi)容"}
        NSString *dataJson = url.query;//拿到后面的json字符串
       NSString *str = [dataJson stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        NSLog(@"%@",str);
//執(zhí)行一段js代碼,彈出提示框
        [webView stringByEvaluatingJavaScriptFromString:@"alert('seccess')"];
        return NO;
    }
    return YES;
    
}

二、使用JavaScriptCore實(shí)現(xiàn)交互

JavaScriptCore是封裝了JavaScript和Objective-C橋接的Objective-C API,只需要較少的的代碼,就可以實(shí)現(xiàn)JavaScript與Objective-C的相互調(diào)用。
  在iOS7之前,只能通過(guò)向UIWebView發(fā)送stringByEvaluatingJavaScriptFromString:消息來(lái)執(zhí)行一段JavaScript的腳本。而且如果想用JavaScript來(lái)調(diào)用Objective-C的方法,必須打開(kāi)一個(gè)自定義的URL(例如:Nanshanyi://),然后在UIWebView的delegate方法webView:shouldStartLoadWithRequest:navigationType中進(jìn)行處理。也就是上問(wèn)中提到的方法
JavaScriptCore中類(lèi)及協(xié)議:
  JSContext:給JavaScript提供運(yùn)行的上下文環(huán)境
  JSValue:JavaScript和Objective-C數(shù)據(jù)和方法的橋梁
   JSManagedValue:管理數(shù)據(jù)和方法的類(lèi)
  JSVirtualMachine:處理線程相關(guān),使用較少
  JSExport:這是一個(gè)協(xié)議,如果采用協(xié)議的方法交互,自己定義的協(xié)議必須遵守此協(xié)議

(1)使用Delegate方式實(shí)現(xiàn)

先放上js的網(wǎng)頁(yè)代碼,可以建一個(gè)HTML文件直接復(fù)制進(jìn)去即可使用

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
</head>
<body>
    <h1>OC和JS的交互代理方式</h1>

    <div>
    <!-- 生成一個(gè) button 添加點(diǎn)擊事件-->
        <input type="button" value="JsToOcShare" onclick="callShare()">
    </div>

<script>
    function callShare() {
        var shareContent = JSON.stringify({"title": "分享", "desc": "分享內(nèi)容", "shareUrl": "http://www.itdecent.cn/users/774b1d5616a7/latest_articles"});
        Nanshanyi.share(shareContent);
    }
    <!--    OC調(diào)JS-->
    function showAlert(message){
        alert(message);
    }
    <!--    JS調(diào)OC成功后回調(diào)-->
    var shareCallback = function(){
        alert('success');
    }
</script>
</body>
</html>
#import <JavaScriptCore/JavaScriptCore.h>
@protocol JSObjcDelegate <JSExport>

- (void)share:(NSString *)shareContent;

@end
@interface ViewController : UIViewController<JSObjcDelegate>
@end

.m文件

#import "ViewController.h"
@interface ViewController ()<UIWebViewDelegate>
@property (nonatomic,strong)UIWebView *webView;
@property (nonatomic,strong)JSContext *jsContext;


@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self CustomUI];

}
- (void)CustomUI{
    self.webView = [[UIWebView alloc]initWithFrame:self.view.bounds];
    self.webView.delegate = self;
    [self.view addSubview:_webView];

    NSURL *url = [[NSBundle mainBundle] URLForResource:@"untitled3" withExtension:@"html"];
    [self.webView loadRequest:[NSURLRequest requestWithURL:url]];
   
}
- (void)webViewDidFinishLoad:(UIWebView *)webView{
    _jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    //代理方式JS調(diào)OC方法
    //Nanshanyi 相當(dāng)于橋接,通過(guò)它將 OC 與 JS 聯(lián)系起來(lái)
    _jsContext[@"Nanshanyi"] = self;
    _jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) {
        context.exception = exceptionValue;
        NSLog(@"異常信息:%@", exceptionValue);
    };
}
- (void)share:(NSString *)shareContent {
    NSLog(@"share:%@", shareContent);
    // 分享成功后,回調(diào)js的方法shareCallback
//    也即是 OC 調(diào)用 JS 方法,只調(diào)用方法,沒(méi)有參數(shù)傳遞
    JSValue *shareCallback = self.jsContext[@"shareCallback"];
    [shareCallback callWithArguments:nil];
}
(2)使用Block方式實(shí)現(xiàn)

同樣放上一段簡(jiǎn)單的JS

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
</head>
<body>
<h1>OC和JS的交互Block方式?</h1>
    <div>
        <input type="button" value="JsToOcShare" onclick="callShare(shareContent)">
    </div>

<script>
    var shareContent = JSON.stringify({"title":"分享", "desc":"分享內(nèi)容", "shareUrl":"http://www.itdecent.cn/users/774b1d5616a7/latest_articles"});
    
    function callShare(share) {
    //share為形參,shareContent為實(shí)參,即要傳遞的參數(shù)
    }
    //  OC調(diào)JS message為傳遞的參數(shù)
    function showAlert(message){
        alert(message);
    }

</script>
</body>
</html>

WebView代理方法的實(shí)現(xiàn)

- (void)showAlert{//直接調(diào)用該方法實(shí)現(xiàn)OC調(diào)用JS,并傳參
    NSString *jsStr = @"showAlert('ios js交互成功,我是網(wǎng)頁(yè) alert')";
    [_jsContext evaluateScript:jsStr];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView{
    _jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    //block 方式 JS直接調(diào)用OC,并傳參,簡(jiǎn)單明了
    __weak typeof  (self)weakSelf = self;
        _jsContext[@"callShare"] =^(id obj){
            weakSelf.lable.text = obj;
    //把傳過(guò)來(lái)的Json字符串,轉(zhuǎn)為字典
            NSData *data = [(NSString *)obj dataUsingEncoding:NSUTF8StringEncoding ];
            NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
            NSLog(@"%@",dict);
            
        };
    _jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) {
        context.exception = exceptionValue;
  //比如把js中的方法名改掉,OC找不到相應(yīng)方法,這里就會(huì)打印異常信息
        NSLog(@"異常信息:%@", exceptionValue);
    };
}

至此,已經(jīng)完成了JS與OC的簡(jiǎn)單交互,實(shí)現(xiàn)了JS與OC方法的相互調(diào)用,與傳值。有什么不對(duì)的請(qǐng)批評(píng)指正,互相學(xué)習(xí)

最后編輯于
?著作權(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)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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