iOS與JavaScript交互總結(jié)

最近跟同事聯(lián)調(diào)一個iOS與JS交互想接口,折騰了整整一天闸准,被迫重新研究了一下iOS與JS交互的原理霎奢,才發(fā)現(xiàn)原來項目中用的方案已經(jīng)是很老很老的方式了户誓,
效率不高,學習成本倒不低幕侠,但總歸之前用了很久都沒出現(xiàn)過什么問題帝美,所以還是簡單的總結(jié)下吧,然后就準備把這套東西淘汰掉用新的方式了橙依。

OC調(diào)用JS

OC調(diào)用JS的方法很簡單证舟,就是UIWebView的stringByEvaluatingJavaScriptFromString方法硕旗,或者
WKWebView的- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;方法。

JS調(diào)用OC

其實現(xiàn)在項目中用的方案原理很簡單女责,就是攔截請求漆枚,然后獲取參數(shù)執(zhí)行OC的方法;
不過為了跟安卓統(tǒng)一抵知,并且方便復用墙基,做了一層封裝,給JS注入方法刷喜。
考慮到js有很多的全局函數(shù)残制,所以直接給js添加方法是不太合適的,可能會導致命名沖突掖疮,比較理想的做法是模塊化初茶,就是給js注入個對象,給這個對象再添加方法浊闪。

具體來說就是:
客戶端這里有一個bridge類恼布,里面有跟js端協(xié)商好的方法;
當網(wǎng)頁加載結(jié)束后(webViewDidFinishLoading)搁宾,iOS這端會執(zhí)行一個方法折汞,取到bridge里面所有方法列表(用runtime方法獲取)盖腿,
然后拼裝成對應的js方法爽待,用evaluateJavaScript方法注入給js,
js需要做的就是在需要的時候調(diào)用對應方法即可翩腐。
注意鸟款,js端除了判斷方法存在不存在和調(diào)用方法,其他什么都沒做栗菜,對象和所有的方法都是客戶端注入的欠雌。
所以這個方案的關(guān)鍵是拼接注入給js的方法,
這里用了一個巧妙的方法疙筹,即利用js可以執(zhí)行字符串中的JavaScript代碼的eval()方法。
iOS端將bridge里獲取的方法列表拼接成字符串禁炒,跟js代碼的字符串拼在一起而咆,拼成一段JavaScript字符串,
然后用webView的evaluateJavaScript方法調(diào)用就可以了
而注入給js的方法幕袱,就是讓js去加載一個指定格式的自定義的URL暴备,然后iOS端攔截這個請求,判斷如果是自定義的URL们豌,則去執(zhí)行自己的方法涯捻,
這里一般是提前一定好一個scheme浅妆,然后根據(jù)后面的字段來區(qū)別不同的方法,
這個方案js傳遞參數(shù)給OC也是很簡單障癌,直接拼在URL后面即可凌外。

理論上OC傳遞參數(shù)給js也是很簡單的,只需js端定義一個帶返回值的函數(shù)涛浙,然后iOS端要拼接這個函數(shù)的調(diào)用的字符串康辑,然后直接用webView的evaluateJavaScript方法調(diào)用它就行了;
但是這跟上面“所有方法都是讓js去load一個自定義格式的URL”的設(shè)計是沖突的轿亮,
因為上面的設(shè)計是疮薇,所有方法都是iOS端注入的,注入的方法內(nèi)容是讓js去load一個自定義URL我注,而這個傳參的js方法不是去load一個自定義的URL按咒,而是去取一個OC執(zhí)行的js的結(jié)果,然后再進行其他操作但骨;
如何解決這個問題呢胖齐?
我自己想到的方法是,在注入方法的時候嗽冒,將注入的方法分為兩類呀伙,一類就是去load自定義URL的方法;另外一種是專門傳遞參數(shù)給js的方法添坊,也就是直接執(zhí)行拼接好的js函數(shù)的方法剿另。
我感覺這個方法是可行的,如果是一些簡單的傳值的方法的話贬蛙,所不定還挺高效雨女,但貌似有一個問題,執(zhí)行結(jié)果貌似是同步傳回給js的阳准,如果OC端執(zhí)行的方法比較耗時氛堕,那可能會卡住js端的進程。
前輩們在項目中使用了個更高級的辦法野蝇,就是調(diào)用js方法時讼稚,如果需要返回值的話,傳一個回調(diào)函數(shù)到OC绕沈∪裣耄回調(diào)函數(shù)固定以一個json字符串作為輸入?yún)?shù)。
為什么說這個方法高級呢乍狐,一是統(tǒng)一了注入給js的方法格式赠摇,而是統(tǒng)一了js注入方法的返回值的格式,三是統(tǒng)一了用異步回調(diào)。
需要注意的是:OC最終調(diào)用的方法只有一個參數(shù)藕帜,這個參數(shù)是一個js傳過來的參數(shù)數(shù)組烫罩,具體參數(shù)數(shù)組里面都是什么內(nèi)容,要在定義注入函數(shù)的時候就跟js端商量好洽故!
(這里還有一個小細節(jié)贝攒,如果沒有參數(shù),OC端的selector是沒有“:”的收津,如果有參數(shù)饿这,一定記得要拼接“:”,否則OC端會識別成不同的函數(shù)名)

回調(diào)函數(shù)還有一個需要注意的地方撞秋,因為OC回調(diào)的是js函數(shù)长捧,所以js端要在某個地方有保存這個函數(shù),直接在調(diào)用注入方法時實現(xiàn)這個函數(shù)貌似是不行的吻贿,必須要建立其調(diào)用js注入函數(shù)與callback函數(shù)之間的對應關(guān)系才行串结,否則oc調(diào)用js回調(diào)是不知道對應的回調(diào)函數(shù)是誰的。舅列。肌割。。帐要。這個比較繞
我又看了下js端同學些的代碼把敞,js端是在傳入callback的同時,將callback函數(shù)保存到一個數(shù)組里面榨惠,然后傳數(shù)組名稱和callback的index給OC奋早,所以O(shè)C端實際調(diào)用的是,拿到數(shù)組里保存的函數(shù)然后傳參數(shù)調(diào)用赠橙。
也就是說耽装,如果是需要OC傳遞參數(shù)給JS的方法,實際上不完全是OC這邊注入的期揪,還是需要JS端同學配合下的掉奄。
這樣看來,跟直接讓JS端同學實現(xiàn)幾個專門的傳參數(shù)方法代價也差不多凤薛。姓建。。

這個方案是UIWebView和WKWebView都可以使用的枉侧。
新的方式也就是iOS7之后的推出的JavaScriptCore引瀑,這個下一篇再寫。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末榨馁,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子帜矾,更是在濱河造成了極大的恐慌翼虫,老刑警劉巖屑柔,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異珍剑,居然都是意外死亡掸宛,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進店門招拙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來唧瘾,“玉大人,你說我怎么就攤上這事别凤∈涡颍” “怎么了?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵规哪,是天一觀的道長求豫。 經(jīng)常有香客問我,道長诉稍,這世上最難降的妖魔是什么蝠嘉? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮杯巨,結(jié)果婚禮上蚤告,老公的妹妹穿的比我還像新娘。我一直安慰自己服爷,他們只是感情好杜恰,可當我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著层扶,像睡著了一般箫章。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上镜会,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天檬寂,我揣著相機與錄音,去河邊找鬼戳表。 笑死桶至,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的匾旭。 我是一名探鬼主播镣屹,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼价涝!你這毒婦竟也來了女蜈?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎伪窖,沒想到半個月后逸寓,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡覆山,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年竹伸,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片簇宽。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡勋篓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出魏割,到底是詐尸還是另有隱情譬嚣,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布见妒,位于F島的核電站孤荣,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏须揣。R本人自食惡果不足惜盐股,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望耻卡。 院中可真熱鬧疯汁,春花似錦、人聲如沸卵酪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽溃卡。三九已至溢豆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間瘸羡,已是汗流浹背漩仙。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留犹赖,地道東北人队他。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像峻村,于是被迫代替她去往敵國和親麸折。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,092評論 2 355

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