作者: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,這個方法完全就是方法重組的案例。