iOS與JS的交互

iOS和JS的交互看似兩個問題,其實要解決的問題只有一個,那就是JS如何調(diào)用native方法。因為查詢文檔我們就可以發(fā)現(xiàn),在UIWebView中,native有直接調(diào)用JS的方法, 但是JS卻沒有直接調(diào)用native的方法。

一、native直接調(diào)用js的方法:

-(NSString*)stringByEvaluatingJavaScriptFromString
:(NSString *)script;

二、JS直接調(diào)用native的方法

其實,UIWebView并沒有提供JS調(diào)用native的方法,但是我們卻可以通過間接的方法來實現(xiàn)這樣的操作??偨Y看來,間接實現(xiàn)的方式有4種:
1. 在代理方法攔截Url,識別判斷
2. Block傳值,實現(xiàn)JS調(diào)用OC
3. 模型實現(xiàn),JS直接用oc方法名來調(diào)用oc方法
4. 使用第三方工具類:WebViewJavascriptBridge
下面就來簡單介紹一下上述方法的簡單實用

1.在代理方法攔截Url,識別判斷

這種方法原理很簡單,UIWebView的界面響應會調(diào)起下面的代理方法

- (BOOL)webView:(UIWebView *)webView 
   shouldStartLoadWithRequest:(NSURLRequest *)request
               navigationType:(UIWebViewNavigationType)navigationType;

在該方法中我們可以識別網(wǎng)頁鏈接中的特殊字段,從而達到JS調(diào)起原生方法的目的

//第一步:使用本地的h5文件加載一個網(wǎng)頁
NSString *htmlPath = [[NSBundle mainBundle] pathForResource:@"testWebPage" ofType:@"html"];
NSError *error = nil;
NSString  *str = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:&error];
[self.webView loadHTMLString:str baseURL:nil];

//h5文件中JS關鍵代碼如下:
<p > 
    <button id="chat" type="button" onclick="location.href    ='http://www.testwebpage/?
    funcName=printInfo:&&info=helloword'">打印信息</button>
</p>

//第二步:攔截協(xié)議
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
        //獲取此時的URL
        //'http://www.testwebpage/?funcName=printInfo:&&info=helloword'
        NSURL *url = [request URL];
        NSString *completeString = [url absoluteString];

        //第一步:檢測鏈接中的特殊字段
        NSString *needCheckStr = @"http://www.testwebpage/?";
        NSRange jumpRange = [completeString rangeOfString:needCheckStr];
        if (jumpRange.location != NSNotFound) {
        /*
         1.檢測到鏈接中包含有特殊字段,客戶端要接受響應并做后續(xù)處理這就相當于js調(diào)起了iOS,
         2.在真實的使用時,客戶端需要和h5協(xié)調(diào),雙方需要統(tǒng)一監(jiān)聽的字段
         3.參數(shù)問題:如果此時的交互需要傳遞參數(shù),參數(shù)也可以放在鏈接里,同樣通過識別字符串的方法來獲取
         */
        //第二步:拿到鏈接字符串的后續(xù)部分,然后分割字符串得到參數(shù)數(shù)據(jù)
        NSMutableString *linkmStr = [NSMutableString stringWithString:completeString];
        NSRange deleteRange = {0,needCheckStr.length};
        [linkmStr deleteCharactersInRange:deleteRange];
        NSArray *params = [linkmStr componentsSeparatedByString:@"&&"];
        //取出第一個參數(shù):與h5協(xié)商好的方法名
        NSString *funcName = [params[0] componentsSeparatedByString:@"="][1];
        //取出第二個參數(shù):信息字符串
        NSString *info = [params[1] componentsSeparatedByString:@"="][1];
        //第三步:調(diào)起iOS原生方法
        SEL ocFunc = NSSelectorFromString(funcName);
        if ([self respondsToSelector:ocFunc]) {
        //使用編譯預處理,不顯示警告提示
        #pragma clang diagnostic push
        #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
            [self performSelector:ocFunc withObject:info];
        #pragma clang diagnostic pop
        }
        //返回NO是為了不再執(zhí)行點擊原鏈接的跳轉
        return NO;
    }
    return YES;
}

2.Block傳值,實現(xiàn)JS調(diào)用OC

這種方法需要引入頭文件
import <JavaScriptCore/JavaScriptCore.h>
具體的代碼操作如下:

JS關鍵代碼:
<p>
  <button onclick="sayHello('helloword')" type="button">問候</button>
</p>
OC關鍵代碼:
- (void)webViewDidFinishLoad:(UIWebView *)webView{
    //獲取JSContext對象
    JSContext *context=[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    //sayHello就是js的方法名稱,使用一個block對應賦值
    __weak typeof (self) weakSelf = self;
    context[@"sayHello"] = ^() {
        NSArray *args = [JSContext currentArguments];
        NSString *objString = [NSString stringWithFormat:@"%@",args[0]] ;
        if (objString.length >0) {
            //得到參數(shù)之后,這里可以使用調(diào)用OC方法,即實現(xiàn)了JS對于OC的調(diào)用
            [weakSelf printInfo:objString];
          }
     };
}

3.模型實現(xiàn),JS直接用oc方法名來調(diào)用oc方法

這種方法的優(yōu)點在于,JS可以直接用oc方法名來調(diào)用oc方法,這樣就類似于安卓的addJavaScriptInterface方法,在使用此方法時仍然要導入JavaScriptCore

//第一步:創(chuàng)建一個用與JS交互的類JSHandler繼承與NSObject
//在類中聲明一個遵守JSExport的協(xié)議,并且使JSHandler實現(xiàn)這個新的協(xié)議
@protocolJSHandlerProtocol <JSExport>
//單參數(shù)方法
- (void)sayHello:(NSString*)greeting;

//多參數(shù)的方法
//由于涉及到多參數(shù)的問題,從第二個參數(shù)開始,外部參數(shù)名都要使用大寫開頭
//因為JS調(diào)用OC方法時,是將OC方法拼接連成字符串,如果無法區(qū)分就會造成無法識別
//比如對于下面的OC方法,JS調(diào)用時
//javascript.sayHelloToWithGreeting(‘參數(shù)1’,參數(shù)2) //正確寫法
//javascript.sayHelloTowithGreeting(‘參數(shù)1’,參數(shù)2) //錯誤寫法
- (void)sayHelloTo:(NSString*)name WithGreeting:(NSString*)greeting;
@end

@interface JSHandler : NSObject<JSHandlerProtocol>

@end
//第二步:實現(xiàn)協(xié)議方法
@implementationJSHandler:NSObject
//單參數(shù)方法
- (void)sayHello:(NSString*)greeting{
    NSLog(@"%s", __func__);
    NSLog(@"%@",greeting);
}

//兩個參數(shù)的方法
- (void)sayHelloTo:(NSString*)name WithGreeting:(NSString*)greeting{
    NSLog(@"%s", __func__);
    NSLog(@"%@,%@",name,greeting);
}

@end

 //第三步:在webView所在的視圖控制中,創(chuàng)建JSContext對象,使用協(xié)議方法
   JSContext*jsContext = [self.webViewvalueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
   JSHandler*jsHandler = [JSHandlernew];
 //使jsContext可以識別javascript這個類的方法
    jsContext[@"javascript"] = jsHandler;
//第四步:此步驟是H5部分的操作,能夠調(diào)起OC方法的代碼如下
       <p>sayHello<buttonid="opennew"type="button"onclick="javascript.sayHello('你好!')">問候1</button></p>
         <p>sayHelloTo<buttonid="opennew2"type="button"onclick=
           "javascript.sayHelloToWithGreeting('zhoushuai', 'Good morning!')">問候2</button></p>

4.使用第三方工具類:WebViewJavascriptBridge

還未使用過,暫時不做過多介紹

demo的github地址:
https://github.com/DreamcoffeeZS/OC-And-JS

參考鏈接:
http://www.cocoachina.com/ios/20160127/15105.html
http://www.itdecent.cn/p/2c7a53713e13

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
禁止轉載,如需轉載請通過簡信或評論聯(lián)系作者。

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

  • 前言 Web 頁面中的 JS 與 iOS Native 如何交互是每個 iOS 猿必須掌握的技能。而說到 Nati...
    幽城88閱讀 2,333評論 1 8
  • 前言 iOS開發(fā)中,用來顯示一個html頁、H5頁,經(jīng)常會用的一個控件是WebView。說到WebView,你知道...
    Dark_Angel閱讀 23,722評論 31 287
  • 最近整理了一下原生與H5之間的交互方式,簡單的做個總結。OC端與JS的交互,大致有這幾種:攔截協(xié)議、JavaScr...
    談Xx閱讀 31,343評論 41 75
  • 自律給我自由 棉花糖和小哈利很久以前就聽過了 自律我感覺像是瑜伽八分支的 持戒 內(nèi)制 練瑜伽的都知道。 長期目標+...
    Fineyoga瑾璟閱讀 110評論 0 0
  • 今天剽悍晨讀介紹的書籍是《故事思維》。 我們?nèi)?,天生喜歡讀故事。相比一個枯燥無味的大道理,一個波瀾起伏、驚心動魄的...
    Chloeeeee_e閱讀 183評論 0 1

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