OC與JS交互

關于UIWebView與JS的交互:

?這里先聲明一下:示例只放上了重點代碼,后面會給demo地址藐吮。

1、原始交互方法:

1谣辞、OC調用JS:向UIWebView發(fā)送- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;消息來執(zhí)行一段JavaScript腳本迫摔;這里需要注意的是:該方法必須在主線程調用,否則不起作用泥从。

  • 同時本人在項目時遇到這樣的需求情況:原生controller進入下一級界面controller句占,該controller存在一個 webView,直接給webView傳遞參數躯嫉,然后點擊H5頁面內按鈕纱烘,webview進入次級界面,再次點擊H5次級頁面內按鈕祈餐,進入下一級原生controller擂啥,而后返回有webView的controller界面并回傳值給webView所在controller,當webView所在controller獲取到返回數據后再傳遞給H5次級頁面帆阳。
    • 這里發(fā)生的問題就是啤它,我在最后一步時回傳值使用的是block,在block內部使用dispatch_async(dispatch_get_main_queue(), ^{})回歸主線程后再調用stringByEvaluatingJavaScriptFromString:向H5發(fā)送參數。但是此時并不能將參數發(fā)送成功变骡,即stringByEvaluatingJavaScriptFromString:不起作用。原因暫時不知芭逝,經排查確實是在主線程了塌碌。
    • 解決方法:傳值方式改為通知中心的方式,然后當收到通知后將參數發(fā)送旬盯。

2台妆、JS調用OC:在UIWebView的代理方法- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;中攔截URL然后重定向去執(zhí)行OC相關代碼;

示例:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    // 原始的JS調用OC胖翰,攔截URL接剩,重定向
    // 這里我在 index.html中采用了兩種方式進行request返回,1:onclick="window.open('need://transform')"萨咳;2:onclick="window.location.href='need://location'"
    if ([request.URL.absoluteString hasPrefix:@"need://transform"]) {// 跳轉
        NSLog(@"執(zhí)行了跳轉操作");
        return NO;
    }
    if ([request.URL.absoluteString hasPrefix:@"need://location"]) {// 本界面的一些操作
        NSLog(@"執(zhí)行了本界面操作");
        return NO;
    }
    return YES;
}

// 這里是點擊了OC中一個原生的button所執(zhí)行的方法
- (void)rightButAction:(UIButton *)sender
{
        // 使用UIWebView自帶方法調用JS方法懊缺,其中picCallback('%@')是JS方法,后面是參數
        NSString * jsStr = [NSString stringWithFormat:@"picCallback('%@')", @"stringByEvaluatingJavaScriptFromString方法實現"];
        [self.mainWebView stringByEvaluatingJavaScriptFromString:jsStr];
}
2培他、使用JavaScriptCore:

? 關于JavaScriptCore框架可以參考這篇文章鹃两,當使用時需要先導入該框架頭文件#import <JavaScriptCore/JavaScriptCore.h>
1舀凛、OC調用JS: 在代理方法- (void)webViewDidFinishLoad:(UIWebView *)webView中獲取交互上下文對象(JSContext) 俊扳,然后調用JSContext- (JSValue *)evaluateScript:(NSString *)script;方法執(zhí)行JS代碼;

2猛遍、JS調用OC:這里有兩種方法馋记,一種是針對JS中未指明調用對象的方法,一種是針對JS中指明調用對象的方法懊烤。

  • 未指明調用對象的方法:可以直接通過context獲取到該方法梯醒,賦予其block的回調方式即可;

  • 指明調用對象的方法:需要創(chuàng)建繼承JSExport的協(xié)議奸晴,協(xié)議方法要與JS中方法相同冤馏!通過context將某一類的實例賦予JS當做調用方法的對象,然后在該類中服從協(xié)議方法即可寄啼;

示例:

// JS調用OC
@protocol JSObjcDelegate <JSExport>
//協(xié)議的方法必須和JS里面的方法名稱保持一致才有效!
- (void)callShare;
@end

@interface JRWebViewMutualViewController ()<UIWebViewDelegate, JSObjcDelegate>
@property (nonatomic,strong) JSContext * jsContext;// 獲取交互環(huán)境逮光,主要用于調取JS代碼
@property(strong,nonatomic)UIWebView * mainWebView;
@end

@implementation JRWebViewMutualViewController

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    self.jsContext = [self.mainWebView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    // 未指明調用對象的方法
    self.jsContext[@"callCamera"] = ^() {
        NSLog(@"調用Camera了??");
    };
    /**
        在JS中 onclick="callCamera()" 指的是點擊button直接觸發(fā)callCamera方法;
        onclick="TEXT.callShare() 指點擊button會讓一個叫做TEXT的對象去觸發(fā)callShare方法;
     */
    //在使用JSExport協(xié)議類時必須有指定的執(zhí)行對象才能使用否則使用block形式的回調即可
    self.jsContext[@"TEXT"] = self;
    // 若發(fā)生異常會執(zhí)行此方法
    self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exception) {
        NSLog(@"異常信息是%@",exception);
    };
}

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
    NSLog(@"加載錯誤:%@", error);
}

// 這里是點擊了OC中一個原生的button所執(zhí)行的方法
- (void)rightButAction:(UIButton *)sender
{
        // 獲取 將字符串對應的JS方法墩划,轉換成一個JSValue對象
        JSValue * jsValue = [self.jsContext evaluateScript:@"picCallback"];
        // 下面??這一方法與上面的等效
//        JSValue * jsValue = self.jsContext[@"picCallback"];
        // 作為一個函數調用JSValue 參數是JS函數所需參數,該方法用于傳參
        [jsValue callWithArguments:@[@"javaScript實現"]];
        
        // 與上面兩句代碼等效代碼
//        [self.jsContext evaluateScript:[NSString stringWithFormat:@"picCallback('%@')", @"javaScript實現"]];
}

- (void)callShare
{
    NSLog(@"調用Share了??");
}
@end

?在這里因為若沒有HTML的代碼可能會不是那么清晰涕刚,附上HTML的代碼,里面比較簡單:

<!DOCTYPE html>  
<html>  
<head lang="zh-CN">
    <meta charset="UTF-8">
    <title>OC-JS交互</title>
</head>  
<body>  
    <div style="margin-top: 30px">
        <input type="button" value="調用OC原生代碼示例 - 攔截協(xié)議乙帮,跳轉界面" onclick="window.open('need://transform')" style = "width:300px;height:30px;border:0px;background-color:red;margin-left:10px" >
    </div>         
  
    <div>  
        <input type="button" value="調用OC原生代碼示例 - 攔截協(xié)議杜漠,本界面做操作" onclick="window.location.href='need://location'" style = "width:300px;height:30px;border-style:none; background-color:#FF9;margin-left:10px; margin-top:10px">
    </div>
    
    <div>
        <p>&lt;1&gt;和后端同事協(xié)定好協(xié)議,如need://transform表示跳轉,need://location表示本界面的其他操作驾茴。 <br>
        &lt;2&gt;實現UIWebView代理的shouldStartLoadWithRequest:navigationType:方法盼樟,在方法中對url進行攔截,如果是步驟 &lt;1&gt; 中定義好的協(xié)議則執(zhí)行對應原生代碼锈至,返回NO進行url攔截晨缴,否則返回YES繼續(xù)加載原url。</p>
    <div>
        
    <div style="margin-top: 10px">
        <input type="button" value="調用OC原生代碼示例 - JSCore,跳轉界面" onclick="callCamera()" style = "width:300px;height:30px;border:0px;background-color:red;margin-left:10px" >
            </div>
    
    <div>
        <input type="button" value="調用OC原生代碼示例 - JSCore峡捡,本界面做操作" onclick="TEXT.callShare()" style = "width:300px;height:30px;border-style:none; background-color:#FF9;margin-left:10px; margin-top:10px">
            </div>
  
<script>  

    var picCallback = function(photos) {  
        alert(photos);  
    }  

</script>

</body>  
</html>  

demo 地址击碗,demo是一個項目集合,暫時沒什么東西们拙,會后續(xù)往里面加入稍途,交互界面在左側抽屜中??。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末砚婆,一起剝皮案震驚了整個濱河市械拍,隨后出現的幾起案子,更是在濱河造成了極大的恐慌射沟,老刑警劉巖殊者,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異验夯,居然都是意外死亡猖吴,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門挥转,熙熙樓的掌柜王于貴愁眉苦臉地迎上來海蔽,“玉大人,你說我怎么就攤上這事绑谣〉炒埽” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵借宵,是天一觀的道長幌衣。 經常有香客問我,道長壤玫,這世上最難降的妖魔是什么豁护? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮欲间,結果婚禮上楚里,老公的妹妹穿的比我還像新娘。我一直安慰自己猎贴,他們只是感情好班缎,可當我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布蝴光。 她就那樣靜靜地躺著,像睡著了一般达址。 火紅的嫁衣襯著肌膚如雪蔑祟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天沉唠,我揣著相機與錄音做瞪,去河邊找鬼。 笑死右冻,一個胖子當著我的面吹牛,可吹牛的內容都是我干的著拭。 我是一名探鬼主播纱扭,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼儡遮!你這毒婦竟也來了乳蛾?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤鄙币,失蹤者是張志新(化名)和其女友劉穎肃叶,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體十嘿,經...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡因惭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了绩衷。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蹦魔。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖咳燕,靈堂內的尸體忽然破棺而出勿决,到底是詐尸還是另有隱情,我是刑警寧澤招盲,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布低缩,位于F島的核電站,受9級特大地震影響曹货,放射性物質發(fā)生泄漏咆繁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一控乾、第九天 我趴在偏房一處隱蔽的房頂上張望么介。 院中可真熱鬧,春花似錦蜕衡、人聲如沸壤短。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽久脯。三九已至纳胧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間帘撰,已是汗流浹背跑慕。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留摧找,地道東北人核行。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像蹬耘,于是被迫代替她去往敵國和親芝雪。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內容