iOS與JS的交互

iOS和JS的交互看似兩個(gè)問題闽寡,其實(shí)要解決的問題只有一個(gè),那就是JS如何調(diào)用native方法着绷。因?yàn)椴樵兾臋n我們就可以發(fā)現(xiàn)芭届,在UIWebView中储矩,native有直接調(diào)用JS的方法, 但是JS卻沒有直接調(diào)用native的方法。

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

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

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

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

1.在代理方法攔截Url,識(shí)別判斷

這種方法原理很簡(jiǎn)單,UIWebView的界面響應(yīng)會(huì)調(diào)起下面的代理方法

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

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

//第一步:使用本地的h5文件加載一個(gè)網(wǎng)頁(yè)
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關(guān)鍵代碼如下:
<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{
        //獲取此時(shí)的URL
        //'http://www.testwebpage/?funcName=printInfo:&&info=helloword'
        NSURL *url = [request URL];
        NSString *completeString = [url absoluteString];

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

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

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

JS關(guān)鍵代碼:
<p>
  <button onclick="sayHello('helloword')" type="button">問候</button>
</p>
OC關(guān)鍵代碼:
- (void)webViewDidFinishLoad:(UIWebView *)webView{
    //獲取JSContext對(duì)象
    JSContext *context=[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    //sayHello就是js的方法名稱,使用一個(gè)block對(duì)應(yīng)賦值
    __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方法砸捏,即實(shí)現(xiàn)了JS對(duì)于OC的調(diào)用
            [weakSelf printInfo:objString];
          }
     };
}

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

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

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

//多參數(shù)的方法
//由于涉及到多參數(shù)的問題掂骏,從第二個(gè)參數(shù)開始,外部參數(shù)名都要使用大寫開頭
//因?yàn)镴S調(diào)用OC方法時(shí)厚掷,是將OC方法拼接連成字符串弟灼,如果無法區(qū)分就會(huì)造成無法識(shí)別
//比如對(duì)于下面的OC方法,JS調(diào)用時(shí)
//javascript.sayHelloToWithGreeting(‘參數(shù)1’冒黑,參數(shù)2) //正確寫法
//javascript.sayHelloTowithGreeting(‘參數(shù)1’袜爪,參數(shù)2) //錯(cuò)誤寫法
- (void)sayHelloTo:(NSString*)name WithGreeting:(NSString*)greeting;
@end

@interface JSHandler : NSObject<JSHandlerProtocol>

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

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

@end

 //第三步:在webView所在的視圖控制中,創(chuàng)建JSContext對(duì)象薛闪,使用協(xié)議方法
   JSContext*jsContext = [self.webViewvalueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
   JSHandler*jsHandler = [JSHandlernew];
 //使jsContext可以識(shí)別javascript這個(gè)類的方法
    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

還未使用過俺陋,暫時(shí)不做過多介紹

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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
禁止轉(zhuǎn)載豁延,如需轉(zhuǎn)載請(qǐng)通過簡(jiǎn)信或評(píng)論聯(lián)系作者。
  • 序言:七十年代末腊状,一起剝皮案震驚了整個(gè)濱河市诱咏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌缴挖,老刑警劉巖袋狞,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異映屋,居然都是意外死亡苟鸯,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門棚点,熙熙樓的掌柜王于貴愁眉苦臉地迎上來早处,“玉大人,你說我怎么就攤上這事瘫析∑霭穑” “怎么了默责?”我有些...
    開封第一講書人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)咸包。 經(jīng)常有香客問我桃序,道長(zhǎng),這世上最難降的妖魔是什么烂瘫? 我笑而不...
    開封第一講書人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任媒熊,我火速辦了婚禮,結(jié)果婚禮上忱反,老公的妹妹穿的比我還像新娘泛释。我一直安慰自己,他們只是感情好温算,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開白布怜校。 她就那樣靜靜地躺著,像睡著了一般注竿。 火紅的嫁衣襯著肌膚如雪茄茁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評(píng)論 1 285
  • 那天巩割,我揣著相機(jī)與錄音裙顽,去河邊找鬼。 笑死宣谈,一個(gè)胖子當(dāng)著我的面吹牛愈犹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播闻丑,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼漩怎,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了嗦嗡?” 一聲冷哼從身側(cè)響起勋锤,我...
    開封第一講書人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎侥祭,沒想到半個(gè)月后叁执,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡矮冬,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年谈宛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胎署。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡入挣,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出硝拧,到底是詐尸還是另有隱情径筏,我是刑警寧澤葛假,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站滋恬,受9級(jí)特大地震影響聊训,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜恢氯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一带斑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧勋拟,春花似錦勋磕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至啸胧,卻和暖如春赶站,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背纺念。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工贝椿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人陷谱。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓烙博,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親烟逊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子渣窜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

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

  • 前言 Web 頁(yè)面中的 JS 與 iOS Native 如何交互是每個(gè) iOS 猿必須掌握的技能。而說到 Nati...
    幽城88閱讀 2,195評(píng)論 1 8
  • 前言 iOS開發(fā)中,用來顯示一個(gè)html頁(yè)囤官、H5頁(yè)冬阳,經(jīng)常會(huì)用的一個(gè)控件是WebView。說到WebView党饮,你知道...
    Dark_Angel閱讀 23,387評(píng)論 31 287
  • 最近整理了一下原生與H5之間的交互方式肝陪,簡(jiǎn)單的做個(gè)總結(jié)。OC端與JS的交互刑顺,大致有這幾種:攔截協(xié)議氯窍、JavaScr...
    談Xx閱讀 31,102評(píng)論 41 75
  • 自律給我自由 棉花糖和小哈利很久以前就聽過了 自律我感覺像是瑜伽八分支的 持戒 內(nèi)制 練瑜伽的都知道饲常。 長(zhǎng)期目標(biāo)+...
    Fineyoga瑾璟閱讀 86評(píng)論 0 0
  • 今天剽悍晨讀介紹的書籍是《故事思維》。 我們?nèi)死翘郑焐矚g讀故事贝淤。相比一個(gè)枯燥無味的大道理,一個(gè)波瀾起伏政供、驚心動(dòng)魄的...
    Chloeeeee_e閱讀 105評(píng)論 0 1