国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

iOS引入JavaScriptCore引擎框架

xavier / 1655人閱讀

摘要:在中,我們可以引入框架,這樣,我們可以層來操作層代碼的執行。都會發送相應的消息給。在端,由于只有暴露在全局的函數聲明才能夠讓端訪問,這就限制了端的靈活性。我們有理由憧憬未來在和下更方便的集成引擎來完成建議的雙向通信。

JavaScriptCore引擎

????我們都知道WebKit是個渲染引擎,簡單來說負責頁面的布局,繪制以及層的合成,但是WebKit工程中不僅僅有關于渲染相關的邏輯,也集成了默認的javascript引擎--JavaScriptCore,目前Safari的js引擎也基于JSC構建,不過有一些私有的優化,總體性能相差不大。JSC的執行理念比較符合傳統的引擎邏輯,它包括了2部分:解釋器和簡單方法JIT。解釋器比較容易理解,針對某種類型的文件解釋執行,在JSC中,它的目標文件是由代碼構建的語法樹生成的字節碼文件,類似于java中的字節碼,不過在JSC中字節碼的執行是在基于寄存器的虛擬機中而不是基于棧,好處在于可以方便的在ARM架構處理器中使用三地址指令,減少了次數較多的出棧和入棧等指令分派以及耗時的內存IO;JIT在java虛擬機中應用比較多,針對執行較多次的熱點方法進行編譯為本地方法,執行效率更高,JSC中的JIT同理。
????在iOS7中,我們可以引入JSC框架,這樣,我們可以oc層來操作js層代碼的執行。另外JSC暴露了許多C層面的接口,我們也可以在底層來構建自定義的js執行環境,操作執行js代碼,可控執行可擴展性更強。

hybrid應用構建

????既然有了這么給力的引擎,我們在構建hybrid app時可以使用JSC來代替cordova的webViewJavascriptBridge框架完成簡易的接口暴露,未來在oc層逐漸可以將UI組件模塊化,并通過JSExport暴露接口,由js層負責調用相應模塊的初始化方法完成界面的hybrid化。
??oc端初始化一個js執行上下文JSContext對象很容易, [[JSContext alloc] init]即可,但是在hybrid app中,通過這種方式初始化JSContext與承載頁面的UIWebVIew并不是同一個js環境,因此我們需要獲取UIWebView對應的JSContext。但是apple官方并未提供相關的方法,不過這邊難不倒某些人,有些人發現,通過KVC的方式可獲取UIWebView對應的JSContext,方式如下[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]。一旦獲取到對應的JSContext,我們可以做的就有很多了。

// 獲取對應的JSContext
JSContext *context=[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

// 設置JSContext的錯誤處理函數
[context setExceptionHandler:^(JSContext *context, JSValue *value) {
    NSLog(@"oc catches the exception: %@", value);
}];

// 組件化某個功能類或UIController   
ShowjoyFad *sf=[ShowjoyFad new];

// 暴露改類至JSContext中,在js層的全局屬性中我們可以訪問該類,如window.showjoyFad
context[@"showjoyFad"]=sf;
context[@"ViewController"] = self;

// 引用js層定義的函數
JSValue * abc = context[@"abc"];
// 執行
JSValue * ret = [abc callWithArguments:@[@"helloworld"]];
NSLog(@"ret: %@",[ret toString]);

????通過簡單的例子可以很明顯的看出JSC通信的簡潔性,與android的WebView通信類似,native端可以直接講接口注入到js上下文中,js在何時的時機調用函數。但是這里涉及到一個比較棘手的問題,JSContext的獲取實在UIWebView的那個階段呢?
????我做過一個測試:首先在UIWebView的webViewDidStartLoad階段創建JSContext并暴露oc端的方法,在加載一級頁面時js正常調用oc的方法,而跳轉到二級頁面中卻無法執行oc的方法;而在webViewDidStartLoad階段由于并未加載完js文件, 因此js層定義的函數在oc端無法執行。
????其次,在webVIewDidFinishLoad階段創建JSContext并透出oc方法,由于加載js階段在webVIewDidFinishLoad階段之前,因此一級頁面js無法調用oc方法,但是二級頁面同理也是如此,但是由于js代碼是在iOS的UI線程執行,因此為了讓js可以調用oc方法,可以通過在js設置setTimeout來讓任務放到執行隊列的末端,先執行oc層的webVIewDidFinishLoad方法,待任務完成后再執行js中的異步代碼,通過這種方式可以完成js調用oc方法;反過來,oc層調用js函數沒有任何問題,因為在webVIewDidFinishLoad階段js代碼已執行完畢(除了異步代碼)。
????為此,可以通過實現一個簡易的框架來完成js層和oc層的交互,為了更好的兼容性,只有在webVIewDidFinishLoad階段創建JSContext。而在js層則有兩種方式來監測并執行oc的方法:

          1,在oc層的webVIewDidFinishLoad階段,暴露oc接口之后,通過JSContext或者UIWebView的stringByEvluateJavascriptString方法構建一個```webViewDidFinishLoad```事件,js端進行偵聽并調用
          2,簡單的通過setTimeout將js的執行順序排至隊列末端

????通過上述方法,構建了一個簡單的JSCBridge,但是缺點也很明顯,對oc端接口暴露時機有硬性要求,并且js執行oc端的代碼始終是異步,有違我們的初衷。

為何放棄第一種方案 UIWebView的JSContext獲取

????上篇中,我們通過簡單的kvc獲取UIWebVIew的JSContext,但是實際上,apple并未給開發者提供訪問UIWebView的方法,雖然通過KVC可達到目標,但是當APP采用該種hack方法時,有很大幾率不能通過APP Store的審核,這對于一個基于上線的商業APP而言是難以忍受的,所以我們必須尋找另一種方法來獲取UIWebView的JSContext而且足夠安全易用,因此我們需轉移目光。

解決 WebFrameLoadDelegate

????在OS X中,WebFrameLoadDelegate負責WebKit與NSWebView的通信,由于NSWebView內部仍然使用WebKit渲染引擎,若要偵聽渲染過程中的一系列事件,則必須使用WebFrameLoadDelegate對象:
????????1、加載過程:

          在一個訪問一個網頁的的整個過程,包括開始加載,加載標題,加載結束等。webkit都會發送相應的消息給WebFrameLoadDelegate 。

              webView:didStartProvisionalLoadForFrame:開始加載,在這里獲取加載的url
              webView:didReceiveTitle:forFrame:獲取到網頁標題
              webView:didFinishLoadForFrame:頁面加載完成

????????2、錯誤的處理:

          加載的過程當中,有可能會發生錯誤。錯誤的消息也會發送給WebFrameLoadDelegate 。我們可以在這兩個函數里面對錯誤信息進行處理

             webView:didFailProvisionalLoadWithError:forFrame: 這個錯誤發生在請求數據之前,最常見是發生在無效的URL或者網絡斷開無法發送請求
             webView:didFailLoadWithError:forFrame: 這個錯誤發生在請求數據之后

????可是在iOS中呢?我嘗試過,并沒有WebFrameLoadDelegate這個對象,看來iOS中的WebKit框架并未提供UIWebView這么多的接口,但是有些人通過WebKit的源碼還是發現了一二,他就是Nick Hodapp。

Nick的發現

????在iOS中,盡管沒有暴露WebFrameLoadDelegate,但是在具體實現上仍會判斷WebKit的implement有沒有實現這個協議的某些方法,如果實現則仍會執行,而且在webit的WebFrameLoaderClient.mm文件中,

if (implementations->didCreateJavaScriptContextForFrameFunc) {
    CallFrameLoadDelegate(implementations->didCreateJavaScriptContextForFrameFunc, webView, @selector(webView:didCreateJavaScriptContext:forFrame:),
        script.javaScriptContext(), m_webFrame.get());
}

會判斷當前的對象有沒有實現webView:didCreateJavaScriptContext:forFrame:方法,有則執行。該方法會傳遞三個參數,第一個是與webkit通信的WebView(此WebView并不是UIWebVIew,Nick層做過測試通過獲取的WebView并不能遍歷到我們需要的UIWebVIew,因此推測,這個WebView是一個UIView的proxy對象,不是UIView類);第二個則是我們想要獲取的JSContext;第三個參數是webkit框架中的WebFrame對象,與我們的期望無關。

????為了讓webkit執行這個函數,我們必須讓對象實現這個方法。由于所有的OC對象都繼承自NSObject對象,因此我們可以在NSObject對象上實現該方法,這樣可以保證該段代碼可以在webkit框架中執行。

????其次,我們既然獲取到了JSContext,但是并不知道JSContext與UIWebVIew的對應關系,我們的ViewController中可能會有多個UIWebView,如何將獲取的JSContext與UIWebview對應起來也是一個難題。在此處有一個簡單的方法,就是獲取所有的UIWebView對象,在每個對象中執行一段js代碼,在js上下文設置一個變量做為標記,然后在我們獲取的JSContext中判斷該變量是否與遍歷的UIWebVIew對象中的對象是否相等來獲取。這樣,我們可以在UIWebView的webViewDidStartLoad和webViewDidFinishLoad之間獲取到JSContext,進行oc和js的雙向通信。

完善

????我們通過上節的闡述,大致明白了Nick的思路,因此可以通過協議和類別來完成這種通信機制,當然采用oc運行時也是可以的。最終oc端接口的代碼放在webView:didCreateJavaScriptContext:forFrame:中,這樣js文件只需加載完畢就可執行oc的接口方法;而oc端要訪問js的接口則可在webVIewDidFinishLoad中執行,完美解決接口訪問時機的問題。
????在js端,由于只有暴露在全局的函數聲明才能夠讓oc端訪問,這就限制了js端的靈活性。我嘗試過在js端通過“賦值”完成接口的暴露(window.say = function(){alert("hello world!")};),在oc端無法訪問,只有通過普通的函數聲明才能解決問題,這可能與JSContext的內存指針引用相關,為了解決此問題,我通過創建一個全局函數來暴露js端的接口對象,通過獲取的對象來訪問具體的接口方法。

 if(isiOS4JSC){
    // 將注冊的方法透出到window.jscObj的屬性上
    var ev = eval;
    $.JSBridge._JSMethod = method;

    // 暴露函數至全局
    // jsc只能執行全局函數聲明方式定義的函數,不可以將函數指針復制給其他變量執行
    ev("function toObjectCExec() {" +
      "window.jscObj = window.jscObj ? window.jscObj : {};"+
      "window.jscObj["" + methodName + ""] = function (message) {" +
      "  var ret = $.JSBridge._JSMethod(message);" +
      "  return JSON.stringify(ret);" +
      "};" +
      "return jscObj;" +
    "}");

  }

如此,js端的接口暴露就很容易了。

尾聲

????我現在仍然相信,目前的iOS hybridAPP的主流通信方式仍然適corava的javascriptWebViewBridge,但是隨著jsc引入到iOS7中,本文介紹的使用jsc(嵌入js引擎的方式)來完成oc和js的通信將更為流行,盡管目前apple提供的針對jsc的開發接口文檔幾乎沒有,但是我們通過webkit的源碼做一些hack的方式也不是不可以,畢竟只要UIWebView仍然使用webkit進行渲染,這種方式會一直有效,除非apple在代碼層面針對hack做過濾,不過這種可能性真的很小。我們有理由憧憬未來在iOS和android下更方便的集成js引擎來完成建議的雙向通信。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/78454.html

相關文章

  • JavaScriptCore 使用

    摘要:在上有這樣一個項目可以拿到了上下文創建的事件,只不過也是改獲取方法也是蘋果的私有,原來項目中使用了這個庫上架蘋果應用商店沒有問題,現在審核情況不太了解。 前言 動態化是移動開發技術中的重要的一部分 ,當前普遍的動態化方案 , 如 React Native 、Weex 、Hybrid部分解決方案及之前流行的熱修復框架 JSPatch ,背后都用到了 JavaScriptCore 框架 ,...

    張遷 評論0 收藏0
  • 跨平臺技術演進

    摘要:接下來,我將從原理優缺點等方面為大家分享跨平臺技術演進。小程序年是微信小程序飛速發展的一年,年,各大廠商快速跟進,已經有了很大的影響力。下面,我們以微信小程序為例,分析小程序的技術架構。 前言 大家好,我是simbawu ,@BooheeFE Team Leader,關于這篇文章,有問題歡迎來這里討論。 隨著移動互聯網的普及和快速發展,手機成了互聯網行業最大的流量分發入口。以及隨著5G...

    魏憲會 評論0 收藏0
  • 跨平臺技術演進

    摘要:接下來,我將從原理優缺點等方面為大家分享跨平臺技術演進。小程序年是微信小程序飛速發展的一年,年,各大廠商快速跟進,已經有了很大的影響力。下面,我們以微信小程序為例,分析小程序的技術架構。 前言 大家好,我是simbawu ,@BooheeFE Team Leader,關于這篇文章,有問題歡迎來這里討論。 隨著移動互聯網的普及和快速發展,手機成了互聯網行業最大的流量分發入口。以及隨著5G...

    MasonEast 評論0 收藏0

發表評論

0條評論

xavier

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<