jspatch 的簡單原理理解

作者:Love@YR 

鏈接:http://blog.csdn.net/jingqiu880905/article/details/51017142

請尊重原創,謝謝!

入口

 [JPEngine startEngine];
    NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"demo" ofType:@"js"];
    NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil];
    [JPEngine evaluateScript:script];

1.把需要運行的demo.js用正則表達式轉換一下

static NSString *_regexStr = @"(?<!\\\\)\\.\\s*(\\w+)\\s*\\(";
static NSString *_replaceStr = @".__c(\"$1\")(";
 NSString *formatedScript = [NSString stringWithFormat:@";(function(){try{\n%@\n}catch(e){_OC_catch(e.message, e.stack)}})();", [_regex stringByReplacingMatchesInString:script options:0 range:NSMakeRange(0, script.length) withTemplate:_replaceStr]];
    @try {
        if ([_context respondsToSelector:@selector(evaluateScript:withSourceURL:)]) {
            return [_context evaluateScript:formatedScript withSourceURL:resourceURL];
        } else {
            return [_context evaluateScript:formatedScript];
        }
    }

這樣轉變之後方法的調用變成_c(‘methodName’)

2.如何知道一個js對象爲oc類?

 調用(global.require)_require方法爲這個js對象加個key:_isCls 並保存類名_clsName

 

3.如何知道一個js對象爲oc對象

js對象的key _obj對應的值便是oc對象返回的指針,如果是oc類則沒有這個key。這個key是oc調用了方法後再包裝傳給js的

 

4.如何表示一個js對象爲oc某個對象的父類對象

js對象的key _isSuper如果爲1則是其父類

 

3.如何調用方法

 

Object.prototype.__c

 

  js的對象基類加一個_c成員方法。這個方法說明如果此對象有_obj(代表其是oc對象轉來的js對象)或者_clsName(代表其是oc類的對象)則告訴它要去調用oc方法。(否則就是普通的js綁定方法)。

 

如果調用的方法名爲super則直接返回這個js對象設置其_isSuper爲1

 

var args = Array.prototype.slice.call(arguments)

拿到參數(參數怎麼拿到的不懂)

 

然後把_obj即包裝過的oc方法返回的指針對象,類名,方法名,

var _methodFunc = function(instance, clsName, methodName, args, isSuper)

 

經過一系列動作拿到了方法的selectorName, 然後根據instance即_obj有無值選擇調用_OC_callI或者_OC_callC 

 

 

4. 看一下js是如何讓oc方法執行的

 

首先app啓動時開啓了js 引擎,創建了js的運行環境,並定義了幾個方法,這些方法可以直接被js調用。(說的是調用這些方法時js參數類型和oc可以互轉)

 

以_OC_callI爲例,分析下其所做的動作。

 

 

調用callSelector:

 

拿到是不是實例,是不是基礎類型,拿到參數,拿到selector,然後invocation設置target ,設置selector ,拿到參數的類型指針設置參數,然後invoke執行方法調用,然後拿到returnValue,再把returnValue從oc對象指針放入dictionary中然後return回js。

js裏 var ret = instance ? _OC_callI(instance, selectorName, args, isSuper):

                         _OC_callC(clsName, selectorName, args)

的ret即爲返回。

然後再把這個dictionary轉成的object轉成js

 

就比如 require('UILabel').alloc().init();

 

這樣就完成了js裏調用_c(‘alloc’)-oc調用方法-oc返回結果(UILabel的對象指針)給js-js再把結果轉成js對象-再調用_c(‘init’)方法

 

5.看一下js如何讓oc重新定義某個方法的實現的

_OC_defineClass

沒有此類,則註冊一個,有的話則調overrideMethod,這個方法完全就是方法重組的案例。

 

發佈了56 篇原創文章 · 獲贊 28 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章