Äú¿ÉÒÔ¾èÖú£¬Ö§³ÖÎÒÃǵĹ«ÒæÊÂÒµ¡£

1Ôª 10Ôª 50Ôª





ÈÏÖ¤Â룺  ÑéÖ¤Âë,¿´²»Çå³þ?Çëµã»÷Ë¢ÐÂÑéÖ¤Âë ±ØÌî



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Modeler   Code  
»áÔ±   
 
   
 
 
     
   
 ¶©ÔÄ
  ¾èÖú
ÌÚѶBugly¼¼Êõ·ÖÏí£ºJSPatchʵÏÖÔ­ÀíÏê½â
 
×÷Õߣºbangchen  À´Ô´£ºÌÚѶBugly  ·¢²¼ÓÚ£º2016-7-13
  2500  次浏览      27
 

JSPatch ÊÇÒ»¸ö iOS ¶¯Ì¬¸üпò¼Ü£¬Ö»ÐèÔÚÏîÄ¿ÖÐÒýÈ뼫СµÄÒýÇæ£¬¾Í¿ÉÒÔʹÓà JavaScript µ÷ÓÃÈκΠObjective-C Ô­Éú½Ó¿Ú£¬»ñµÃ½Å±¾ÓïÑÔµÄÓÅÊÆ£ºÎªÏîÄ¿¶¯Ì¬Ìí¼ÓÄ£¿é£¬»òÌæ»»ÏîĿԭÉú´úÂ붯̬ÐÞ¸´ bug¡£

֮ǰÔÚ²©¿ÍÉÏд¹ýÁ½Æª JSPatch Ô­Àí½âÎöÎÄÕÂ( 1 2)£¬µ«Ëæ×Å JSPatch µÄ¸Ä½ø£¬ÓÐЩÄÚÈÝÒѾ­¸ú×îдúÂë¶Ô²»ÉÏ£¬ÕâÀïÖØÐÂÕûÀí³ÉһƪÍêÕûµÄÎÄÕ£¬¶ÔÔ­À´µÄÁ½Æª×öÕûºÏºÍÐ޸ģ¬Ïêϸ²ûÊö JSPatch µÄʵÏÖÔ­ÀíºÍһЩϸ½Ú£¬ÒÔ°ïÖúʹÓÃÕ߸üºÃµØÁ˽âºÍʹÓà JSPatch¡£

»ù´¡Ô­Àí

JSPatch ÄÜ×öµ½Í¨¹ý JS µ÷Óú͸Äд OC ·½·¨×î¸ù±¾µÄÔ­ÒòÊÇ Objective-C ÊǶ¯Ì¬ÓïÑÔ£¬OC ÉÏËùÓз½·¨µÄµ÷ÓÃ/ÀàµÄÉú³É¶¼Í¨¹ý Objective-C Runtime ÔÚÔËÐÐʱ½øÐУ¬ÎÒÃÇ¿ÉÒÔͨ¹ýÀàÃû/·½·¨Ãû·´ÉäµÃµ½ÏàÓ¦µÄÀàºÍ·½·¨£º

Class class = NSClassFromString("UIViewController");  
id viewController = [[class alloc] init];
SEL selector = NSSelectorFromString("viewDidLoad");
[viewController performSelector:selector];

Ò²¿ÉÒÔÌæ»»Ä³¸öÀàµÄ·½·¨ÎªÐµÄʵÏÖ£º

static void newViewDidLoad(id slf, SEL sel) {}  
class_replaceMethod(class, selector, newViewDidLoad, @""); ;

»¹¿ÉÒÔÐÂ×¢²áÒ»¸öÀ࣬ΪÀàÌí¼Ó·½·¨£º

Class cls = objc_allocateClassPair(superCls, "JPObject", 0);  
objc_registerClassPair(cls);
class_addMethod(cls, selector, implement, typedesc);

¶ÔÓÚ Objective-C ¶ÔÏóÄ£ÐͺͶ¯Ì¬ÏûÏ¢·¢Ë͵ÄÔ­ÀíÒÑÓкܶàÎÄÕ²ûÊöµÃºÜÏêϸ£¬ÕâÀï¾Í²»Ïêϸ²ûÊöÁË¡£ÀíÂÛÉÏÄã¿ÉÒÔÔÚÔËÐÐʱͨ¹ýÀàÃû/·½·¨Ãûµ÷Óõ½ÈκΠOC ·½·¨£¬Ìæ»»ÈκÎÀàµÄʵÏÖÒÔ¼°ÐÂÔöÈÎÒâÀà¡£ËùÒÔ JSPatch µÄ»ù±¾Ô­Àí¾ÍÊÇ£ºJS ´«µÝ×Ö·û´®¸ø OC£¬OC ͨ¹ý Runtime ½Ó¿Úµ÷ÓúÍÌæ»» OC ·½·¨¡£ÕâÊÇ×î»ù´¡µÄÔ­Àí£¬Êµ¼ÊʵÏÖ¹ý³Ì»¹Óкܶà¹ÖÒª´ò£¬½ÓÏÂÀ´¿´¿´¾ßÌåÊÇÔõÑùʵÏֵġ£

·½·¨µ÷ÓÃ

require('UIView')  
var view = UIView.alloc().init()
view.setBackgroundColor(require('UIColor').grayColor())
view.setAlpha(0.5)

ÒýÈë JSPatch ºó£¬¿ÉÒÔͨ¹ýÒÔÉÏ JS ´úÂë´´½¨ÁËÒ»¸ö UIView ʵÀý£¬²¢ÉèÖñ³¾°ÑÕÉ«ºÍ͸Ã÷¶È£¬º­¸ÇÁË require ÒýÈëÀ࣬JS µ÷Óýӿڣ¬ÏûÏ¢´«µÝ£¬¶ÔÏó³ÖÓкÍת»»£¬²ÎÊýת»»ÕâÎå¸ö·½Ã棬½ÓÏÂÀ´ÖðÒ»¿´¿´¾ßÌåʵÏÖ¡£

1. require

µ÷Óà require('UIView') ºó£¬¾Í¿ÉÒÔÖ±½ÓʹÓà UIView Õâ¸ö±äÁ¿È¥µ÷ÓÃÏàÓ¦µÄÀà·½·¨ÁË£¬require ×öµÄʺܼòµ¥£¬¾ÍÊÇÔÚJSÈ«¾Ö×÷ÓÃÓòÉÏ´´½¨Ò»¸öͬÃû±äÁ¿£¬±äÁ¿Ö¸ÏòÒ»¸ö¶ÔÏ󣬶ÔÏóÊôÐÔ__isCls±íÃ÷ÕâÊÇÒ»¸öClass£¬__clsName±£´æÀàÃû£¬ÔÚµ÷Ó÷½·¨Ê±»áÓõ½ÕâÁ½¸öÊôÐÔ¡£

var _require = function(clsName) {  
if (!global[clsName]) {
global[clsName] = {
__isCls: 1,
__clsName: clsName
}
}
return global[clsName]
}

ËùÒÔµ÷Óà require('UIView') ºó£¬¾ÍÔÚÈ«¾Ö×÷ÓÃÓòÉú³ÉÁË UIView Õâ¸ö±äÁ¿£¬Ö¸ÏòÒ»¸öÕâÑùÒ»¸ö¶ÔÏó£º

{  
__isCls: 1,
__clsName: "UIView"
} !

2. JS½Ó¿Ú

½ÓÏÂÀ´¿´¿´ UIView.alloc() ÊÇÔõÑùµ÷Óõġ£

i. ·â×° JS ¶ÔÏó

¶ÔÓÚÕâ¸öµ÷ÓõÄʵÏÖ£¬Ò»¿ªÊ¼ÎÒµÄÏë·¨ÊÇ£¬¸ù¾ÝJSÌØÐÔ£¬ÈôÒªÈà UIView.alloc() Õâ¾äµ÷Óò»³ö´í£¬Î¨Ò»µÄ·½·¨¾ÍÊǸø UIView Õâ¸ö¶ÔÏóÌí¼Ó alloc ·½·¨£¬²»È»ÊDz»¿ÉÄܵ÷Óóɹ¦µÄ£¬JS ¶ÔÓÚµ÷ÓÃû¶¨ÒåµÄÊôÐÔ/±äÁ¿£¬Ö»»áÂíÉÏÅ׳öÒì³££¬¶ø²»Ïñ OC/Lua/Ruby ÄÇÑù»áÓÐת·¢»úÖÆ¡£ËùÒÔ×öÁËÒ»¸ö¸´ÔÓµÄÊ£¬¾ÍÊÇÔÚRequireÉú³ÉÀà¶ÔÏóʱ£¬°ÑÀàÃû´«ÈëOC£¬OC ͨ¹ýRuntime·½·¨ÕÒ³öÕâ¸öÀàËùÓеķ½·¨·µ»Ø¸ø JS£¬JS Àà¶ÔÏóΪÿ¸ö·½·¨Ãû¶¼Éú³ÉÒ»¸öº¯Êý£¬º¯ÊýÄÚÈݾÍÊÇÄÃ×Å·½·¨ÃûÈ¥ OC µ÷ÓÃÏàÓ¦·½·¨¡£Éú³ÉµÄ UIView ¶ÔÏó´óÖÂÊÇÕâÑùµÄ£º

{  
__isCls: 1,
__clsName: "UIView",
alloc: function() {¡­},
beginAnimations_context: function() {¡­},
setAnimationsEnabled: function(){¡­},
...
}

ʵ¼ÊÉϲ»½öÒª±éÀúµ±Ç°ÀàµÄËùÓз½·¨£¬»¹ÒªÑ­»·ÕÒ¸¸ÀàµÄ·½·¨Ö±µ½¶¥²ã£¬Õû¸ö¼Ì³ÐÁ´ÉϵÄËùÓз½·¨¶¼Òª¼Óµ½JS¶ÔÏóÉÏ£¬Ò»¸öÀà¾ÍÓм¸°Ù¸ö·½·¨£¬ÕâÑù°Ñ·½·¨È«²¿¼Óµ½ JS ¶ÔÏóÉÏ£¬Åöµ½ÁËͦÑÏÖØµÄÎÊÌ⣬ÒýÈ뼸¸öÀà¾ÍÄڴ汩ÕÇ£¬ÎÞ·¨Ê¹Ó᣺óÀ´ÎªÁËÓÅ»¯ÄÚ´æÎÊÌ⻹ÔÚ JS ¸ãÁ˼̳йØÏµ£¬²»°Ñ¼Ì³ÐÁ´ÉÏËùÓз½·¨¶¼Ìí¼Óµ½Ò»¸öJS¶ÔÏ󣬱ÜÃâÏñ»ùÀà NSObject µÄ¼¸°Ù¸ö·½·¨·´¸´Ìí¼ÓÔÚÿ¸ö JS ¶ÔÏóÉÏ£¬Ã¿¸ö·½·¨Ö»´æÔÚÒ»·Ý£¬JS ¶ÔÏó¸´ÖÆÁË OC ¶ÔÏóµÄ¼Ì³Ð¹ØÏµ£¬ÕÒ·½·¨Ê±ÑØ×ż̳ÐÁ´ÍùÉÏÕÒ£¬½á¹ûÄÚ´æÏûºÄÊÇСÁËһЩ£¬µ«»¹ÊÇ´óµ½ÄÑÒÔ½ÓÊÜ¡£

ii. __c()Ôªº¯Êý

µ±Ê±¼ÌÐø¿à¿àѰÕÒ½â¾ö·½°¸£¬Èô°´ JS Óï·¨£¬ÕâÊÇΨһµÄ·½·¨£¬µ«Èô²»°´ JS Óï·¨ÄØ£¿Í»È»ÄÔ¶´¿ªÁËÏ£¬CoffieScript/JSX ¶¼¿ÉÒÔÓà JS ʵÏÖÒ»¸ö½âÊÍÆ÷ʵÏÖ×Ô¼ºµÄÓï·¨£¬ÎÒÒ²¿ÉÒÔͨ¹ýÀàËÆµÄ·½Ê½×öµ½£¬ÔÙ½øÒ»²½Ïëµ½ÆäʵÎÒÏëÒªµÄЧ¹ûºÜ¼òµ¥£¬¾ÍÊǵ÷ÓÃÒ»¸ö²»´æÔÚ·½·¨Ê±£¬ÄÜת·¢µ½Ò»¸öÖ¸¶¨º¯ÊýÈ¥Ö´ÐУ¬¾ÍÄܽâ¾öÒ»ÇÐÎÊÌâÁË£¬ÕâÆäʵ¿ÉÒÔÓüòµ¥µÄ×Ö·û´®Ìæ»»£¬°Ñ JS ½Å±¾ÀïµÄ·½·¨µ÷Óö¼Ìæ»»µô¡£×îºóµÄ½â¾ö·½°¸ÊÇ£¬ÔÚ OC Ö´ÐÐ JS ½Å±¾Ç°£¬Í¨¹ýÕýÔò°ÑËùÓз½·¨µ÷Óö¼¸Ä³Éµ÷Óà __c() º¯Êý£¬ÔÙÖ´ÐÐÕâ¸ö JS ½Å±¾£¬×öµ½ÁËÀàËÆ OC/Lua/Ruby µÈµÄÏûϢת·¢»úÖÆ£º

UIView.alloc().init()  
->
UIView.__c('alloc')().__c('init')()

¸ø JS ¶ÔÏó»ùÀà Object µÄ prototype ¼ÓÉÏ __c ³ÉÔ±£¬ÕâÑùËùÓжÔÏ󶼿ÉÒÔµ÷Óõ½ __c£¬¸ù¾Ýµ±Ç°¶ÔÏóÀàÐÍÅжϽøÐв»Í¬²Ù×÷£º

Object.prototype.__c = function(methodName) {  
if (!this.__obj && !this.__clsName) return this[methodName].bind(this);
var self = this
return function(){
var args = Array.prototype.slice.call(arguments)
return _methodFunc(self.__obj, self.__clsName, methodName, args, self.__isSuper)
}
}

_methodFunc() ¾ÍÊǰÑÏà¹ØÐÅÏ¢´«¸øOC£¬OCÓà Runtime ½Ó¿Úµ÷ÓÃÏàÓ¦·½·¨£¬·µ»Ø½á¹ûÖµ£¬Õâ¸öµ÷ÓþͽáÊøÁË¡£

ÕâÑù×ö²»ÓÃÈ¥ OC ±éÀú¶ÔÏó·½·¨£¬²»ÓÃÔÚ JS ¶ÔÏó±£´æÕâЩ·½·¨£¬ÄÚ´æÏûºÄÖ±½µ 99%£¬ÕâÒ»²½ÊÇ×öÕâ¸öÏîÄ¿×îˬµÄʱºò£¬ÓÃÒ»¸ö·Ç³£¼òµ¥µÄ·½·¨½â¾öÁËÑÏÖØµÄÎÊÌâ£¬Ìæ»»Ö®Ç°ÓÖ¸´ÔÓЧ¹ûÓÖ²îµÄʵÏÖ¡£

3.ÏûÏ¢´«µÝ

½â¾öÁË JS ½Ó¿ÚÎÊÌ⣬½ÓÏÂÀ´¿´¿´ JS ºÍ OC ÊÇÔõÑù»¥´«ÏûÏ¢µÄ¡£ÕâÀïÓõ½ÁË JavaScriptCore µÄ½Ó¿Ú£¬OC ¶ËÔÚÆô¶¯ JSPatch ÒýÇæÊ±»á´´½¨Ò»¸ö JSContext ʵÀý£¬JSContext ÊÇ JS ´úÂëµÄÖ´Ðл·¾³£¬¿ÉÒÔ¸ø JSContext Ìí¼Ó·½·¨£¬JS ¾Í¿ÉÒÔÖ±½Óµ÷ÓÃÕâ¸ö·½·¨£º

JSContext *context = [[JSContext alloc] init];  
context[@"hello"] = ^(NSString *msg) {
NSLog(@"hello %@", msg);
};
[_context evaluateScript:@"hello('word')"]; //output hello word

JS ͨ¹ýµ÷Óà JSContext ¶¨ÒåµÄ·½·¨°ÑÊý¾Ý´«¸ø OC£¬OC ͨ¹ý·µ»ØÖµ´«»á¸ø JS¡£µ÷ÓÃÕâÖÖ·½·¨£¬ËüµÄ²ÎÊý/·µ»ØÖµ JavaScriptCore ¶¼»á×Ô¶¯×ª»»£¬OC ÀïµÄ NSArray, NSDictionary, NSString, NSNumber, NSBlock »á·Ö±ðתΪJS¶ËµÄÊý×é/¶ÔÏó/×Ö·û´®/Êý×Ö/º¯ÊýÀàÐÍ¡£ÉÏÊö _methodFunc ·½·¨¾ÍÊÇÕâÑù°ÑÒªµ÷ÓõÄÀàÃûºÍ·½·¨Ãû´«µÝ¸ø OC µÄ¡£

4.¶ÔÏó³ÖÓÐ/ת»»

½áºÏÉÏÊö¼¸µã£¬¿ÉÒÔÖªµÀ UIView.alloc() Õâ¸öÀà·½·¨µ÷ÓÃÓï¾äÊÇÔõÑùÖ´Ðеģº

a.require('UIView') Õâ¾ä»°ÔÚ JS È«¾Ö×÷ÓÃÓòÉú³ÉÁË UIView Õâ¸ö¶ÔÏó£¬ËüÓиöÊôÐԽР__isCls£¬±íʾÕâ´ú±íÒ»¸ö OC Àà¡£

b.µ÷Óà UIView Õâ¸ö¶ÔÏóµÄ alloc() ·½·¨£¬»áÈ¥µ½ __c() º¯Êý£¬ÔÚÕâ¸öº¯ÊýÀïÅжϵ½µ÷ÓÃÕß __isCls ÊôÐÔ£¬ÖªµÀËüÊÇ´ú±í OC À࣬°Ñ·½·¨ÃûºÍÀàÃû´«µÝ¸ø OC Íê³Éµ÷Óá£

µ÷ÓÃÀà·½·¨¹ý³ÌÊÇÕâÑù£¬ÄÇʵÀý·½·¨ÄØ£¿UIView.alloc() »á·µ»ØÒ»¸ö UIView ʵÀý¶ÔÏó¸ø JS£¬Õâ¸ö OC ʵÀý¶ÔÏóÔÚ JS ÊÇÔõÑù±íʾµÄ£¿ÔõÑù¿ÉÒÔÔÚ JS Äõ½Õâ¸öʵÀý¶ÔÏóºó¿ÉÒÔÖ±½Óµ÷ÓÃËüµÄʵÀý·½·¨ UIView.alloc().init()£¿

¶ÔÓÚÒ»¸ö×Ô¶¨Òåid¶ÔÏó£¬JavaScriptCore »á°ÑÕâ¸ö×Ô¶¨Òå¶ÔÏóµÄÖ¸Õë´«¸ø JS£¬Õâ¸ö¶ÔÏóÔÚ JS ÎÞ·¨Ê¹Ó㬵«Ôڻش«¸ø OC ʱ OC ¿ÉÒÔÕÒµ½Õâ¸ö¶ÔÏó¡£¶ÔÓÚÕâ¸ö¶ÔÏóÉúÃüÖÜÆÚµÄ¹ÜÀí£¬°´ÎÒµÄÀí½âÈç¹ûJSÓбäÁ¿ÒýÓÃʱ£¬Õâ¸ö OC ¶ÔÏóÒýÓüÆÊý¾Í¼Ó1 £¬JS ±äÁ¿µÄÒýÓÃÊÍ·ÅÁ˾ͼõ1£¬Èç¹û OC ÉÏû±ðµÄ³ÖÓÐÕߣ¬Õâ¸öOC¶ÔÏóµÄÉúÃüÖÜÆÚ¾Í¸ú×Å JS ×ßÁË£¬»áÔÚ JS ½øÐÐÀ¬»ø»ØÊÕʱÊÍ·Å¡£

´«»Ø¸ø JS µÄ±äÁ¿ÊÇÕâ¸ö OC ¶ÔÏóµÄÖ¸Õ룬Õâ¸öÖ¸ÕëÒ²¿ÉÒÔÖØÐ´«»Ø OC£¬ÒªÔÚ JS µ÷ÓÃÕâ¸ö¶ÔÏóµÄij¸öʵÀý·½·¨£¬¸ù¾ÝµÚ2µã JS ½Ó¿ÚµÄÃèÊö£¬Ö»ÐèÔÚ __c() º¯ÊýÀï°ÑÕâ¸ö¶ÔÏóÖ¸ÕëÒÔ¼°ËüÒªµ÷Óõķ½·¨Ãû´«»Ø¸ø OC ¾ÍÐÐÁË£¬ÏÖÔÚÎÊÌâֻʣÏ£ºÔõÑùÔÚ __c() º¯ÊýÀïÅжϵ÷ÓÃÕßÊÇÒ»¸ö OC ¶ÔÏóÖ¸Õ룿

ĿǰûÕÒµ½·½·¨ÅжÏÒ»¸ö JS ¶ÔÏóÊÇ·ñ±íʾ OC Ö¸Õ룬ÕâÀïµÄ½â¾ö·½·¨ÊÇÔÚ OC °Ñ¶ÔÏ󷵻ظø JS ֮ǰ£¬ÏȰÑËü°ü×°³ÉÒ»¸ö NSDictionary£º

static NSDictionary *_wrapObj(id obj) {  
return @{@"__obj": obj};
} !

Èà OC ¶ÔÏó×÷ΪÕâ¸ö NSDictionary µÄÒ»¸öÖµ£¬ÕâÑùÔÚ JS ÀïÕâ¸ö¶ÔÏó¾Í±ä³É£º

{__obj: [OC Object ¶ÔÏóÖ¸Õë]}  

ÕâÑù¾Í¿ÉÒÔͨ¹ýÅж϶ÔÏóÊÇ·ñÓÐ __obj ÊôÐÔµÃÖªÕâ¸ö¶ÔÏóÊÇ·ñ±íʾ OC ¶ÔÏóÖ¸Õ룬ÔÚ __c º¯ÊýÀïÈôÅжϵ½µ÷ÓÃÕßÓÐ __obj ÊôÐÔ£¬È¡³öÕâ¸öÊôÐÔ£¬¸úµ÷ÓõÄʵÀý·½·¨Ò»Æð´«»Ø¸ø OC£¬¾ÍÍê³ÉÁËʵÀý·½·¨µÄµ÷Óá£

5.ÀàÐÍת»»

JS °ÑÒªµ÷ÓõÄÀàÃû/·½·¨Ãû/¶ÔÏ󴫸ø OC ºó£¬OC µ÷ÓÃÀà/¶ÔÏóÏàÓ¦µÄ·½·¨ÊÇͨ¹ý NSInvocation ʵÏÖ£¬ÒªÄÜ˳Àûµ÷Óõ½·½·¨²¢È¡µÃ·µ»ØÖµ£¬Òª×öÁ½¼þÊ£º

a.È¡µÃÒªµ÷ÓÃµÄ OC ·½·¨¸÷²ÎÊýÀàÐÍ£¬°Ñ JS ´«À´µÄ¶ÔÏóתΪҪÇóµÄÀàÐͽøÐе÷Óᣠb.¸ù¾Ý·µ»ØÖµÀàÐÍÈ¡³ö·µ»ØÖµ£¬°üװΪ¶ÔÏ󴫻ظø JS¡£

ÀýÈ翪ͷÀý× view.setAlpha(0.5)£¬ JS´«µÝ¸øOCµÄÊÇÒ»¸ö NSNumber£¬OC ÐèҪͨ¹ýÒªµ÷Óà OC ·½·¨µÄ NSMethodSignature µÃÖªÕâÀï²ÎÊýÒªµÄÊÇÒ»¸ö float ÀàÐÍÖµ£¬ÓÚÊÇ°Ñ NSNumber תΪ float ÖµÔÙ×÷Ϊ²ÎÊý½øÐÐ OC ·½·¨µ÷Óá£ÕâÀïÖ÷Òª´¦ÀíÁË int/float/bool µÈÊýÖµÀàÐÍ£¬²¢¶Ô CGRect/CGRange µÈÀàÐͽøÐÐÁËÌØÊâת»»´¦Àí£¬Ê£ÏµľÍÊÇʵÏÖϸ½ÚÁË¡£

·½·¨Ìæ»»

JSPatch ¿ÉÒÔÓà defineClass ½Ó¿ÚÈÎÒâÌæ»»Ò»¸öÀàµÄ·½·¨£¬·½·¨Ìæ»»µÄʵÏÖ¹ý³ÌÒ²ÊÇÆÄΪÇúÕÛ£¬Ò»¿ªÊ¼ÊÇÓà va_list µÄ·½Ê½»ñÈ¡²ÎÊý£¬½á¹û·¢ÏÖ arm64 ϲ»¿ÉÓã¬Ö»ÄÜת¶øÓÃÁíÒ»ÖÖ hack ·½Ê½ÈƵÀʵÏÖ¡£ÁíÍâÔÚ¸øÀàÐÂÔö·½·¨¡¢ÊµÏÖproperty¡¢Ö§³Öself/super¹Ø¼ü×ÖÉÏÒ²·ÑÁËЩ¹¦·ò£¬ÏÂÃæÖð¸ö˵Ã÷¡£

1.»ù´¡Ô­Àí

OCÉÏ£¬Ã¿¸öÀà¶¼ÊÇÕâÑùÒ»¸ö½á¹¹Ì壺

struct objc_class {  
struct objc_class * isa;
const char *name;
¡­.
struct objc_method_list **methodLists; /*·½·¨Á´±í*/
};

ÆäÖÐ methodList ·½·¨Á´±íÀï´æ´¢µÄÊÇ Method ÀàÐÍ£º

typedef struct objc_method *Method;  
typedef struct objc_ method {
SEL method_name;
char *method_types;
IMP method_imp;
};

Method ±£´æÁËÒ»¸ö·½·¨µÄÈ«²¿ÐÅÏ¢£¬°üÀ¨ SEL ·½·¨Ãû£¬type ¸÷²ÎÊýºÍ·µ»ØÖµÀàÐÍ£¬IMP ¸Ã·½·¨¾ßÌåʵÏֵĺ¯ÊýÖ¸Õë¡£

ͨ¹ý Selector µ÷Ó÷½·¨Ê±£¬»á´Ó methodList Á´±íÀïÕÒµ½¶ÔÓ¦Method½øÐе÷Óã¬Õâ¸ö methodList ÉϵÄÔªËØÊÇ¿ÉÒÔ¶¯Ì¬Ìæ»»µÄ£¬¿ÉÒÔ°Ñij¸ö Selector ¶ÔÓ¦µÄº¯ÊýÖ¸ÕëIMPÌæ»»³Éеģ¬Ò²¿ÉÒÔÄõ½ÒÑÓеÄij¸ö Selector ¶ÔÓ¦µÄº¯ÊýÖ¸ÕëIMP£¬ÈÃÁíÒ»¸ö Selector ¸úËü¶ÔÓ¦£¬Runtime ÌṩÁËһЩ½Ó¿Ú×öÕâЩÊ£¬ÒÔÌæ»» UIViewController µÄ -viewDidLoad: ·½·¨ÎªÀý£º

static void viewDidLoadIMP (id slf, SEL sel) {  
JSValue *jsFunction = ¡­;
[jsFunction callWithArguments:nil];
}

Class cls = NSClassFromString(@"UIViewController");
SEL selector = @selector(viewDidLoad);
Method method = class_getInstanceMethod(cls, selector);

//»ñµÃviewDidLoad·½·¨µÄº¯ÊýÖ¸Õë
IMP imp = method_getImplementation(method)

//»ñµÃviewDidLoad·½·¨µÄ²ÎÊýÀàÐÍ
char *typeDescription = (char *)method_getTypeEncoding(method);

//ÐÂÔöÒ»¸öORIGViewDidLoad·½·¨£¬Ö¸ÏòÔ­À´µÄviewDidLoadʵÏÖ
class_addMethod(cls, @selector(ORIGViewDidLoad), imp, typeDescription);

//°ÑviewDidLoad IMPÖ¸Ïò×Ô¶¨ÒåеÄʵÏÖ
class_replaceMethod(cls, selector, viewDidLoadIMP, typeDescription);

ÕâÑù¾Í°Ñ UIViewController µÄ -viewDidLoad ·½·¨¸øÌæ»»³ÉÎÒÃÇ×Ô¶¨ÒåµÄ·½·¨£¬APPÀïµ÷Óà UIViewController µÄ viewDidLoad ·½·¨¶¼»áÈ¥µ½ÉÏÊö viewDidLoadIMP º¯ÊýÀÔÚÕâ¸öеÄIMPº¯ÊýÀïµ÷Óà JS ´«½øÀ´µÄ·½·¨£¬¾ÍʵÏÖÁËÌæ»» viewDidLoad ·½·¨ÎªJS´úÂëÀïµÄʵÏÖ£¬Í¬Ê±Îª UIViewController ÐÂÔöÁ˸ö·½·¨ -ORIGViewDidLoad Ö¸ÏòÔ­À´ viewDidLoad µÄ IMP£¬JS ¿ÉÒÔͨ¹ýÕâ¸ö·½·¨µ÷Óõ½Ô­À´µÄʵÏÖ¡£

·½·¨Ìæ»»¾ÍÕâÑùºÜ¼òµ¥µÄʵÏÖÁË£¬µ«Õâô¼òµ¥µÄǰÌáÊÇ£¬Õâ¸ö·½·¨Ã»ÓвÎÊý¡£Èç¹ûÕâ¸ö·½·¨ÓвÎÊý£¬ÔõÑù°Ñ²ÎÊýÖµ´«¸øÎÒÃÇÐ嵀 IMP º¯ÊýÄØ£¿ÀýÈç UIViewController µÄ -viewDidAppear: ·½·¨£¬µ÷ÓÃÕ߻ᴫһ¸ö Bool Öµ£¬ÎÒÃÇÐèÒªÔÚ×Ô¼ºÊµÏÖµÄIMP£¨ÉÏÊöµÄ viewDidLoadIMP£©ÉÏÄõ½Õâ¸öÖµ£¬ÔõÑùÄÜÄõ½£¿Èç¹ûÖ»ÊÇÕë¶ÔÒ»¸ö·½·¨Ð´ IMP£¬ÊÇ¿ÉÒÔÖ±½ÓÄõ½Õâ¸ö²ÎÊýÖµµÄ£º

static void viewDidAppear (id slf, SEL sel, BOOL animated) {  
[function callWithArguments:@(animated)];
}

µ«ÎÒÃÇÒªµÄÊÇʵÏÖÒ»¸öͨÓõÄIMP£¬ÈÎÒâ·½·¨ÈÎÒâ²ÎÊý¶¼¿ÉÒÔͨ¹ýÕâ¸öIMPÖÐת£¬Äõ½·½·¨µÄËùÓвÎÊý»Øµ÷JSµÄʵÏÖ¡£

2.va_listʵÏÖ(32λ)

×î³õÎÒÊÇÓÿɱä²ÎÊý va_list ʵÏÖ£º

static void commonIMP(id slf, ...)  
va_list args;
va_start(args, slf);
NSMutableArray *list = [[NSMutableArray alloc] init];
NSMethodSignature *methodSignature =
[cls instanceMethodSignatureForSelector:selector];
NSUInteger numberOfArguments
= methodSignature.numberOfArguments;
id obj;
for (NSUInteger i = 2; i < numberOfArguments; i++) {
const char *argumentType =
[methodSignature getArgumentTypeAtIndex:i];
switch(argumentType[0]) {
case 'i':
obj = @(va_arg(args, int));
break;
case 'B':
obj = @(va_arg(args, BOOL));
break;
case 'f':
case 'd':
obj = @(va_arg(args, double));
break;
¡­¡­ //ÆäËûÊýÖµÀàÐÍ
default: {
obj = va_arg(args, id);
break;
}
}
[list addObject:obj];
}
va_end(args);
[function callWithArguments:list];
}


ÕâÑùÎÞÂÛ·½·¨²ÎÊýÊÇʲô£¬ÓжàÉÙ¸ö£¬¶¼¿ÉÒÔͨ¹ý va_listµÄÒ»×é·½·¨Ò»¸ö¸öÈ¡³öÀ´£¬×é³É NSArray ÔÚµ÷Óà JS ·½·¨Ê±´«»Ø¡£ºÜÍêÃÀµØ½â¾öÁ˲ÎÊýµÄÎÊÌ⣬һֱÔËÐÐÕý³££¬Ö±µ½ÎÒÅÜÔÚ arm64 µÄ»ú×ÓÉϲâÊÔ£¬Ò»µ÷ÓÃ¾Í crash¡£²éÁË×ÊÁÏ£¬²Å·¢ÏÖ arm64 Ï va_list µÄ½á¹¹¸Ä±äÁË£¬µ¼ÖÂÎÞ·¨ÉÏÊöÕâÑùÈ¡²ÎÊý¡£Ïê¼ûÕâÆªÎÄÕ£ºhttps://blog.nelhage.com/2010/10/amd64-and-va_arg¡£

3.ForwardInvocationʵÏÖ(64λ)

¼ÌÐøÑ°ÕÒ½â¾ö·½°¸£¬×îºóÕÒµ½ÁíÒ»Öַdz£ hack µÄ·½·¨½â¾ö²ÎÊý»ñÈ¡µÄÎÊÌ⣬ÀûÓÃÁË OC ÏûϢת·¢»úÖÆ¡£

µ±µ÷ÓÃÒ»¸ö NSObject ¶ÔÏó²»´æÔڵķ½·¨Ê±£¬²¢²»»áÂíÉÏÅ׳öÒì³££¬¶øÊǻᾭ¹ý¶à²ãת·¢£¬²ã²ãµ÷ÓöÔÏóµÄ -resolveInstanceMethod:, -forwardingTargetForSelector:, -methodSignatureForSelector:, -forwardInvocation: µÈ·½·¨£¬ÆäÖÐ×îºó -forwardInvocation: ÊÇ»áÓÐÒ»¸ö NSInvocation ¶ÔÏó£¬Õâ¸ö NSInvocation ¶ÔÏó±£´æÁËÕâ¸ö·½·¨µ÷ÓõÄËùÓÐÐÅÏ¢£¬°üÀ¨ Selector Ãû£¬²ÎÊýºÍ·µ»ØÖµÀàÐÍ£¬×îÖØÒªµÄÊÇÓÐËùÓвÎÊýÖµ£¬¿ÉÒÔ´ÓÕâ¸ö NSInvocation ¶ÔÏóÀïÄõ½µ÷ÓõÄËùÓвÎÊýÖµ¡£ÎÒÃÇ¿ÉÒÔÏë°ì·¨ÈÃÿ¸öÐèÒª±» JS Ìæ»»µÄ·½·¨µ÷ÓÃ×îºó¶¼µ÷µ½ -forwardInvocation:£¬¾Í¿ÉÒÔ½â¾öÎÞ·¨Äõ½²ÎÊýÖµµÄÎÊÌâÁË¡£

¾ßÌåʵÏÖ£¬ÒÔÌæ»» UIViewController µÄ -viewWillAppear: ·½·¨ÎªÀý£º

°ÑUIViewControllerµÄ -viewWillAppear: ·½·¨Í¨¹ý class_replaceMethod() ½Ó¿ÚÖ¸Ïò _objc_msgForward£¬ÕâÊÇÒ»¸öÈ«¾Ö IMP£¬OC µ÷Ó÷½·¨²»´æÔÚʱ¶¼»áת·¢µ½Õâ¸ö IMP ÉÏ£¬ÕâÀïÖ±½Ó°Ñ·½·¨Ìæ»»³ÉÕâ¸ö IMP£¬ÕâÑùµ÷ÓÃÕâ¸ö·½·¨Ê±¾Í»á×ßµ½ -forwardInvocation:¡£
ΪUIViewControllerÌí¼Ó -ORIGviewWillAppear: ºÍ -_JPviewWillAppear: Á½¸ö·½·¨£¬Ç°ÕßÖ¸ÏòÔ­À´µÄIMPʵÏÖ£¬ºóÕßÊÇеÄʵÏÖ£¬ÉÔºó»áÔÚÕâ¸öʵÏÖÀï»Øµ÷JSº¯Êý¡£
¸ÄдUIViewControllerµÄ -forwardInvocation: ·½·¨Îª×Ô¶¨ÒåʵÏÖ¡£Ò»µ©OCÀïµ÷Óà UIViewController µÄ -viewWillAppear: ·½·¨£¬¾­¹ýÉÏÃæµÄ´¦Àí»á°ÑÕâ¸öµ÷ÓÃת·¢µ½ -forwardInvocation: £¬ÕâʱÒѾ­×é×°ºÃÁËÒ»¸ö NSInvocation£¬°üº¬ÁËÕâ¸öµ÷ÓõIJÎÊý¡£ÔÚÕâÀï°Ñ²ÎÊý´Ó NSInvocation ·´½â³öÀ´£¬´ø×ŲÎÊýµ÷ÓÃÉÏÊöÐÂÔö¼ÓµÄ·½·¨ -JPviewWillAppear: £¬ÔÚÕâ¸öз½·¨ÀïÈ¡µ½²ÎÊý´«¸øJS£¬µ÷ÓÃJSµÄʵÏÖº¯Êý¡£Õû¸öµ÷Óõ÷Óùý³Ì¾Í½áÊøÁË£¬Õû¸ö¹ý³ÌͼʾÈçÏ£º

×îºóÒ»¸öÎÊÌ⣬ÎÒÃÇ°Ñ UIViewController µÄ -forwardInvocation: ·½·¨µÄʵÏÖ¸øÌæ»»µôÁË£¬Èç¹û³ÌÐòÀïÕæÓÐÓõ½Õâ¸ö·½·¨¶ÔÏûÏ¢½øÐÐת·¢£¬Ô­À´µÄÂß¼­Ôõô°ì£¿Ê×ÏÈÎÒÃÇÔÚÌæ»» -forwardInvocation: ·½·¨Ç°»áн¨Ò»¸ö·½·¨ -ORIGforwardInvocation:£¬±£´æÔ­À´µÄʵÏÖIMP£¬ÔÚÐ嵀 -forwardInvocation: ʵÏÖÀï×öÁ˸öÅжϣ¬Èç¹ûת·¢µÄ·½·¨ÊÇÎÒÃÇÏë¸ÄдµÄ£¬¾Í×ßÎÒÃǵÄÂß¼­£¬Èô²»ÊÇ£¬¾Íµ÷ -ORIGforwardInvocation: ×ßÔ­À´µÄÁ÷³Ì¡£

ÆäËû¾ÍÊÇʵÏÖÉϵÄϸ½ÚÁË£¬ÀýÈçÐèÒª¸ù¾Ý²»Í¬µÄ·µ»ØÖµÀàÐÍÉú³É²»Í¬µÄ IMP£¬ÒªÔÚ¸÷´¦´¦Àí²ÎÊýת»»µÈ¡£

4. ÐÂÔö·½·¨

i. ·½°¸

ÔÚ JSPatch ¸Õ¿ªÔ´Ê±£¬ÊDz»Ö§³ÖΪһ¸öÀàÐÂÔö·½·¨µÄ£¬ÒòΪ¾õµÃÄÜÌæ»»Ô­Éú·½·¨¾Í¹»ÁË£¬Ðµķ½·¨´¿´âÌí¼ÓÔÚ JS ¶ÔÏóÉÏ£¬Ö»ÔÚ JS ¶ËÅܾÍÐÐÁË¡£ÁíÍâ OC ΪÀàÐÂÔö·½·¨ÐèÒªÖªµÀ¸÷¸ö²ÎÊýºÍ·µ»ØÖµµÄÀàÐÍ£¬ÐèÒªÔÚ JS ¶¨Ò»ÖÖ·½Ê½°ÑÕâЩÀàÐÍ´«¸ø OC ²ÅÄÜÍê³ÉÐÂÔö·½·¨£¬±È½ÏÂé·³¡£ºóÀ´Í¦¶àÈ˱ȽϹØ×¢Õâ¸öÎÊÌ⣬²»ÄÜÐÂÔö·½·¨µ¼Ö action-target ģʽÎÞ·¨Óã¬ÎÒÒ²¿ªÊ¼ÏëÓÐûÓиüºÃµÄ·½·¨ÊµÏÖÌí¼Ó·½·¨¡£ºóÀ´µÄ½â¾ö·½°¸ÊÇËùÓÐÀàÐͶ¼Óà id ±íʾ£¬ÒòΪ·´ÕýÐÂÔöµÄ·½·¨¶¼ÊÇ JS ÔÚÓÃ(Protocol¶¨ÒåµÄ·½·¨³ýÍâ)£¬²»ÈçÐÂÔöµÄ·½·¨·µ»ØÖµºÍ²ÎÊýȫͳһ³É id ÀàÐÍ£¬ÕâÑù¾Í²»Óô«ÀàÐÍÁË¡£

ÏÖÔÚ defineClass ¶¨ÒåµÄ·½·¨»á¾­¹ý JS °ü×°£¬±ä³ÉÒ»¸ö°üº¬²ÎÊý¸öÊýºÍ·½·¨ÊµÌåµÄÊý×é´«¸øOC£¬OC»áÅжÏÈç¹û·½·¨ÒÑ´æÔÚ£¬¾ÍÖ´ÐÐÌæ»»µÄ²Ù×÷£¬Èô²»´æÔÚ£¬¾Íµ÷Óà class_addMethod() ÐÂÔöÒ»¸ö·½·¨£¬Í¨¹ý´«¹ýÀ´µÄ²ÎÊý¸öÊýºÍ·½·¨ÊµÌåÉú³ÉÐ嵀 Method£¬°Ñ Method µÄ²ÎÊýºÍ·µ»ØÖµÀàÐͶ¼ÉèΪid¡£ÕâÀï JS µ÷ÓÃÐÂÔö·½·¨×ßµÄÁ÷³Ì»¹ÊÇ forwardInvocation ÕâÒ»Ìס£

ii. Protocol

¶ÔÓÚÐÂÔöµÄ·½·¨»¹ÓиöÎÊÌ⣬Èôij¸öÀàʵÏÖÁËij protocol£¬protocol·½·¨ÀïÓпÉÑ¡µÄ·½·¨£¬ËüµÄ²ÎÊý²»È«ÊÇ id ÀàÐÍ£¬ÀýÈç UITableViewDataSource µÄÒ»¸ö·½·¨£º

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString  
*)title atIndex:(NSInteger)index;

ÈôÔ­ÀàûÓÐʵÏÖÕâ¸ö·½·¨£¬ÔÚ JS ÀïʵÏÖÁË£¬»á×ßµ½ÐÂÔö·½·¨µÄÂß¼­£¬Ã¿¸ö²ÎÊýÀàÐͶ¼±ä³É id£¬ÓëÕâ¸ö protocol ·½·¨²»Æ¥Å䣬²úÉú´íÎó¡£

ÕâÀï¾ÍÐèÒªÔÚ JS ¶¨ÒåÀàʱ¸ø³öʵÏÖµÄ protocol£¬ÕâÑùÔÚÐÂÔö Protocol ÀïÒѶ¨ÒåµÄ·½·¨Ê±£¬²ÎÊýÀàÐͻᰴÕÕ Protocol ÀïµÄ¶¨ÒåȥʵÏÖ£¬Protocol µÄ¶¨Ò巽ʽ¸ú OC ÉϵÄд·¨Ò»Ö£º

defineClass("JPViewController: UIViewController <UIAlertViewDelegate>", {  
alertView_clickedButtonAtIndex: function(alertView, buttonIndex) {
console.log('clicked index ' + buttonIndex)
}
})

ʵÏÖ·½Ê½±È½Ï¼òµ¥£¬Ï顄 Protocol Ãû½âÎö³öÀ´£¬µ± JS ¶¨ÒåµÄ·½·¨ÔÚÔ­ÓÐÀàÉÏÕÒ²»µ½Ê±£¬ÔÙͨ¹ý objc_getProtocol ºÍ protocol_copyMethodDescriptionList runtime ½Ó¿Ú°Ñ Protocol ¶ÔÓ¦µÄ·½·¨È¡³öÀ´£¬ÈôÆ¥ÅäÉÏ£¬Ôò°´Æä·½·¨µÄ¶¨Òå×ß·½·¨Ìæ»»µÄÁ÷³Ì¡£

5. PropertyʵÏÖ

ÈôÒªÔÚ JS ²Ù×÷ OC ¶ÔÏóÉÏÒѶ¨ÒåºÃµÄ property£¬Ö»ÐèÒªÏñµ÷ÓÃÆÕͨ OC ·½·¨Ò»Ñù£¬µ÷ÓÃÕâ¸ö¶ÔÏóµÄ get/set ·½·¨¾ÍÐÐÁË£º

//OC @property (nonatomic) NSString *data; @property (nonatomic) BOOL  
*succ; ``` ``` //JS self.setSucc(1); var str = self.data();

[
ÈôÒª¶¯Ì¬¸ø OC ¶ÔÏóÐÂÔö property£¬ÔòÒªÁí±Ùõè¾¶£º

defineClass('JPTableViewController : UITableViewController', {  
dataSource: function() {
var data = self.getProp('data')
if (data) return data;
data = [1,2,3]
self.setProp_forKey(data, 'data')
return data;
}
}

JSPatch¿ÉÒÔͨ¹ý -getProp:£¬ -setProp:forKey: ÕâÁ½¸ö·½·¨¸ø¶ÔÏó¶¯Ì¬Ìí¼Ó³ÉÔ±±äÁ¿¡£ÊµÏÖÉÏÓÃÁËÔËÐÐʱ¹ØÁª½Ó¿Ú objc_getAssociatedObject() ºÍ objc_setAssociatedObject() Ä£Ä⣬Ï൱ÓÚ°ÑÒ»¸ö¶ÔÏó¸úµ±Ç°¶ÔÏóself¹ØÁªÆðÀ´£¬ÒÔºó¿ÉÒÔͨ¹ýµ±Ç°¶ÔÏóselfÕÒµ½Õâ¸ö¶ÔÏ󣬸ú³ÉÔ±µÄЧ¹ûÒ»Ñù£¬Ö»ÊÇÒ»¶¨µÃÊÇid¶ÔÏóÀàÐÍ¡£

±¾À´OCÓÐ class_addIvar() ¿ÉÒÔΪÀàÌí¼Ó³ÉÔ±£¬µ«±ØÐëÔÚÀà×¢²á֮ǰÌí¼ÓÍ꣬ע²áÍê³ÉºóÎÞ·¨Ìí¼Ó£¬ÕâÒâζ×Å¿ÉÒÔΪÔÚJSÐÂÔöµÄÀàÌí¼Ó³ÉÔ±£¬µ«²»ÄÜΪOCÉÏÒÑ´æÔÚµÄÀàÌí¼Ó£¬ËùÒÔÖ»ÄÜÓÃÉÏÊö·½·¨Ä£Äâ¡£

6. self¹Ø¼ü×Ö

defineClass("JPViewController: UIViewController", {  
viewDidLoad: function() {
var view = self.view()
...
},
}

JSPatchÖ§³ÖÖ±½ÓÔÚdefineClassÀïµÄʵÀý·½·¨ÀïÖ±½ÓʹÓà self ¹Ø¼ü×Ö£¬¸úOCÒ»Ñù self ÊÇÖ¸µ±Ç°¶ÔÏó£¬Õâ¸ö self ¹Ø¼ü×ÖÊÇÔõÑùʵÏÖµÄÄØ£¿Êµ¼ÊÉÏÕâ¸öselfÊǸöÈ«¾Ö±äÁ¿£¬ÔÚ defineClass Àï¶ÔʵÀý·½·¨ ·½·¨½øÐÐÁ˰ü×°£¬ÔÚµ÷ÓÃʵÀý·½·¨Ö®Ç°£¬»á°ÑÈ«¾Ö±äÁ¿ self ÉèΪµ±Ç°¶ÔÏ󣬵÷ÓÃÍêºóÉè»Ø¿Õ£¬¾Í¿ÉÒÔÔÚÖ´ÐÐʵÀý·½·¨µÄ¹ý³ÌÖÐʹÓà self ±äÁ¿ÁË¡£ÕâÊÇÒ»¸öССµÄtrick¡£

7. super¹Ø¼ü×Ö

defineClass("JPViewController: UIViewController", {  
viewDidLoad: function() {
self.super.viewDidLoad()
},
}

OC Àï super ÊÇÒ»¸ö¹Ø¼ü×Ö£¬ÎÞ·¨Í¨¹ý¶¯Ì¬·½·¨Äõ½ super£¬ÄÇô JSPatch µÄ super ÊÇÔõôʵÏֵģ¿Êµ¼ÊÉϵ÷Óà super µÄ·½·¨£¬OC ×öµÄÊÂÊǵ÷Óø¸ÀàµÄij¸ö·½·¨£¬²¢°Ñµ±Ç°¶ÔÏóµ±³É self ´«È븸Àà·½·¨£¬ÎÒÃÇֻҪģÄâËüÕâ¸ö¹ý³Ì¾ÍÐÐÁË¡£

Ê×ÏÈ JS ¶ËÐèÒª¸æËßOCÏëµ÷ÓõÄÊǵ±Ç°¶ÔÏóµÄ super ·½·¨£¬×ö·¨Êǵ÷Óà self.super()ʱ£¬__c º¯Êý»á×öÌØÊâ´¦Àí£¬·µ»ØÒ»¸öеĶÔÏó£¬Õâ¸ö¶ÔÏóͬÑù±£´æÁË OC ¶ÔÏóµÄÒýÓã¬Í¬Ê±±êʶ __isSuper = 1¡£

...  
if (methodName == 'super') {
return function() {
return {__obj: self.__obj, __clsName: self.__clsName, __isSuper: 1}
}
}
...

ÔÙÓÃÕâ¸ö·µ»ØµÄ¶ÔÏóÈ¥µ÷Ó÷½·¨Ê±£¬__c º¯Êý»á°Ñ __isSuper Õâ¸ö±êʶλ´«¸ø OC£¬¸æËß OC Òªµ÷ super µÄ·½·¨¡£OC ×öµÄÊÂÇéÊÇ£¬Èç¹ûÊǵ÷Óà super ·½·¨£¬ÕÒµ½ superClass Õâ¸ö·½·¨µÄ IMP ʵÏÖ£¬Îªµ±Ç°ÀàÐÂÔöÒ»¸ö·½·¨Ö¸Ïò super µÄ IMP ʵÏÖ£¬ÄÇôµ÷ÓÃÕâ¸öÀàµÄз½·¨¾ÍÏ൱ÓÚµ÷Óà super ·½·¨¡£°ÑÒªµ÷Óõķ½·¨Ìæ»»³ÉÕâ¸öз½·¨£¬¾ÍÍê³É super ·½·¨µÄµ÷ÓÃÁË¡£

static id callSelector(NSString *className, NSString *selectorName, 
NSArray *arguments, id instance, BOOL isSuper) {
...
if (isSuper) {
NSString *superSelectorName =
NSString stringWithFormat:@"SUPER_%@",
selectorName];
SEL superSelector = NSSelectorFromString(superSelectorName);

Class superCls = [cls superclass];
Method superMethod =
class_getInstanceMethod(superCls, selector);
IMP superIMP =
method_getImplementation(superMethod);

class_addMethod(cls, superSelector, superIMP,
method_getTypeEncoding(superMethod));
selector = superSelector;
}
...
}

À©Õ¹

1. Struct Ö§³Ö

struct ÀàÐÍÔÚ JS Óë OC ¼ä´«µÝÐèÒª×öת»»´¦Àí£¬Ò»¿ªÊ¼ JSPatch Ö»´¦ÀíÁËÔ­ÉúµÄ NSRange / CGRect / CGSize / CGPoint ÕâËĸö£¬ÆäËû struct ÀàÐÍÎÞ·¨ÔÚ OC / JS ¼ä´«µÝ¡£¶ÔÓÚÆäËûÀàÐ굀 struct Ö§³Ö£¬ÎÒÊDzÉÓÃÀ©Õ¹µÄ·½Ê½£¬ÈÃдÀ©Õ¹µÄÈËÊÖ¶¯´¦Àíÿ¸öÒªÖ§³ÖµÄ struct ½øÐÐÀàÐÍת»»£¬ÕâÖÖ×ö·¨Ã»ÎÊÌ⣬µ«ÐèÒªÔÚ OC ´úÂëдºÃÕâЩÀ©Õ¹£¬ÎÞ·¨¶¯Ì¬Ìí¼Ó£¬×ª»»µÄʵÏÖÒ²±È½Ï·±Ëö¡£ÓÚÊÇתΪÁíÒ»ÖÖʵÏÖ£º

/* 
struct JPDemoStruct {
CGFloat a;
long b;
double c;
BOOL d;
}
*/
require('JPEngine').defineStruct({
"name": "JPDemoStruct",
"types": "FldB",
"keys": ["a", "b", "c", "d"]
})

¿ÉÒÔÔÚ JS ¶¯Ì¬¶¨ÒåÒ»¸öÐ嵀 struct£¬Ö»ÐèÌṩ struct Ãû£¬Ã¿¸ö×ֶεÄÀàÐÍÒÔ¼°Ã¿¸ö×ֶζÔÓ¦µÄÔÚ JS µÄ¼üÖµ£¬¾Í¿ÉÒÔÖ§³ÖÕâ¸ö struct ÀàÐÍÔÚ JS ºÍ OC ¼ä´«µÝÁË£º

//OC  
@implementation JPObject
+ (void)passStruct:(JPDemoStruct)s;
+ (JPDemoStruct)returnStruct;
@end

//JS  
require('JPObject').passStruct({a:1, b:2, c:4.2, d:1})
var s = require('JPObject').returnStruct();

ÕâÀïµÄʵÏÖÔ­ÀíÊÇ˳Ðòȥȡ struct Àïÿ¸ö×ֶεÄÖµ£¬ÔÙ¸ù¾Ý key ÖØÐ°ü×°³É NSDictionary ´«¸ø JS£¬ÔõÑù˳ÐòÈ¡ struct ÿ×ֶεÄֵĨ£¿¿ÉÒÔ¸ù¾Ý´«½øÀ´µÄ struct ×ֶεıäÁ¿ÀàÐÍ£¬Äõ½ÀàÐͶÔÓ¦µÄ³¤¶È£¬Ë³Ðò¿½±´³ö struct ¶ÔӦλÖúͳ¤¶ÈµÄÖµ£¬¾ßÌåʵÏÖ£º

for (int i = 0; i < types.count; i ++) {  
size_t size = sizeof(types[i]); //types[i] ÊÇ float double int µÈÀàÐÍ
void *val = malloc(size);
memcpy(val, structData + position, size);
position += size;
}

struct ´Ó JS µ½ OC µÄת»»Í¬Àí£¬Ö»ÊÇ·´¹ýÀ´£¬ÏÈÉú³ÉÕû¸ö struct ´óСµÄÄÚ´æµØÖ·£¨Í¨¹ý struct ËùÓÐ×Ö¶ÎÀàÐÍ´óСÀÛ¼Ó£©£¬ÔÙÖð½¥È¡³ö JS ´«¹ýÀ´µÄÖµ½øÐÐÀàÐÍת»»¿½±´µ½Õâ¶ËÄÚ´æÀï¡£

ÕâÖÖ×ö·¨Ð§¹ûºÜºÃ£¬JS ¶ËÒªÓÃÒ»¸öÐ嵀 struct ÀàÐÍ£¬²»ÐèÒª OC ÊÂÏȶ¨ÒåºÃ£¬¿ÉÒÔÖ±½Ó¶¯Ì¬Ìí¼ÓÐ嵀 struct ÀàÐÍÖ§³Ö£¬µ«ÕâÖÖ·½·¨ÒÀÀµ struct ¸÷¸ö×Ö¶ÎÔÚÄÚ´æ¿Õ¼äÉϵÄÑϸñÅÅÁУ¬Èç¹ûijЩ»úÆ÷ÔڵײãʵÏÖÉÏ¶Ô struct µÄ×ֶνøÐÐһЩ×Ö½Ú¶ÔÆëÖ®ÀàµÄ´¦Àí£¬ÕâÖÖ·½Ê½Ã»·¨ÓÃÁË£¬²»¹ýĿǰÔÚ iOS ÉÏ»¹Ã»Åöµ½ÕâÑùµÄÎÊÌâ¡£

2. C º¯ÊýÖ§³Ö

C º¯Êýû·¨Í¨¹ý·´ÉäÈ¥µ÷Óã¬ËùÒÔÖ»ÄÜͨ¹ýÊÖ¶¯×ª½ÓµÄ·½Ê½Èà JS µ÷ C ·½·¨£¬¾ßÌå¾ÍÊÇͨ¹ý JavaScriptCore µÄ·½·¨ÔÚ JS µ±Ç°×÷ÓÃÓòÉ϶¨ÒåÒ»¸ö C º¯ÊýͬÃû·½·¨£¬ÔÚÕâ¸ö·½·¨ÊµÏÖÀïµ÷Óà C º¯Êý£¬ÒÔÖ§³Ö memcpy() ΪÀý£º

context[@"memcpy"] = ^(JSValue *des, JSValue *src, size_t n) {  
memcpy(des, src, n);
};

ÕâÑù¾Í¿ÉÒÔÔÚ JS µ÷Óà memcpy() º¯ÊýÁË¡£Êµ¼ÊÉÏÕâÀﻹÓвÎÊý JS <-> OC ת»»ÎÊÌ⣬ÕâÀïÏȺöÂÔ¡£

ÕâÀïÓÐÁ½¸öÎÊÌ⣺

a.Èç¹ûÕâЩ C º¯ÊýµÄÖ§³Ö¶¼Ð´ÔÚ JSPatch Ô´ÎļþÀԴÎļþ»á·Ç³£ÅÓ´ó¡£

b.Èç¹ûÒ»¿ªÊ¼¾Í¸ø JS ¼ÓÕâЩº¯Êý¶¨Ò壬ÈôÒªÖ§³ÖµÄ C º¯ÊýÁ¿´óʱ»áÓ°ÏìÐÔÄÜ¡£

¶Ô´ËÉè¼ÆÁËÒ»ÖÖÀ©Õ¹µÄ·½Ê½È¥½â¾öÕâÁ½¸öÎÊÌ⣬JSPatch ÐèÒª×öµÄ¾ÍÊÇΪÍⲿÌṩ JS ÔËÐÐÉÏÏÂÎÄ JSContext£¬ÒÔ¼°²ÎÊýת»»µÄ·½·¨£¬×îÖÕÉè¼Æ³öÀ´µÄÀ©Õ¹½Ó¿ÚÊÇÕâÑù£º

@interface JPExtension : NSObject  
+ (void)main:(JSContext *)context;

+ (void *)formatPointerJSToOC:(JSValue *)val;
+ (id)formatPointerOCToJS:(void *)pointer;
+ (id)formatJSToOC:(JSValue *)val;
+ (id)formatOCToJS:(id)obj;

@end

s +main ·½·¨±©Â¶ÁË JSPatch µÄÔËÐл·¾³ JSContext ¸øÍⲿ£¬¿ÉÒÔ×ÔÓÉÔÚÕâ¸ö JSContext ÉϼӺ¯Êý¡£ÁíÍâËĸö formatXXX ·½·¨¶¼ÊDzÎÊýת»»·½·¨¡£ÉÏÊöµÄ memcpy() ÍêÕûµÄÀ©Õ¹¶¨ÒåÈçÏ£º

@implementation JPMemory  
+ (void)main:(JSContext *)context
{
context[@"memcpy"] = ^id(JSValue *des, JSValue *src, size_t n) {
void *ret = memcpy([self formatPointerJSToOC:des], [self formatPointerJSToOC:src], n);
return [self formatPointerOCToJS:ret];
};
}
@end

ͬʱ JSPatch ÌṩÁË +addExtensions: ½Ó¿Ú£¬Èà JS ¶Ë¿ÉÒÔ¶¯Ì¬¼ÓÔØÄ³¸öÀ©Õ¹£¬ÔÚÐèÒªµÄʱºòÔÙ¸ø JS ÉÏÏÂÎÄÌí¼ÓÕâЩ C º¯Êý£º

require('JPEngine').addExtensions(['JPMemory'])  

ʵ¼ÊÉÏ»¹ÓÐÁíÒ»ÖÖ·½·¨Ìí¼Ó C º¯ÊýµÄÖ§³Ö£¬¾ÍÊǶ¨Òå OC ·½·¨×ª½Ó£º

@implementation JPCFunctions  
+ (void)memcpy:(void *)des src:(void *)src n:(size_t)n {
memcpy(des, src, n);
}
@end

È»ºóÖ±½ÓÔÚ JS ÉÏÕâÑùµ÷£º

require('JPFunctions').memcpy_src_n(des, src, n); 

ÕâÑùµÄ×ö·¨²»ÐèÒªÀ©Õ¹»úÖÆ£¬Ò²²»ÐèÒªÔÚʵÏÖʱ½øÐвÎÊýת»»£¬µ«ÒòΪËü×ßµÄÊÇ OC runtime ÄÇÒ»Ì×£¬Ïà±ÈÀ©Õ¹Ö±½Óµ÷Óõķ½Ê½£¬ËÙ¶ÈÂýÁËÒ»±¶£¬ÎªÁ˸üºÃµÄÐÔÄÜ£¬»¹ÊÇÌṩһÌ×À©Õ¹½Ó¿Ú¡£

ϸ½Ú

Õû¸ö JSPatch µÄ»ù´¡Ô­ÀíÉÏÃæ´óÖ²ûÊöÍêÁË£¬½ÓÏÂÀ´ÔÚ¿´¿´Ò»Ð©ÊµÏÖÉÏÅöµ½µÄ¿ÓºÍµÄϸ½ÚÎÊÌâ¡£

1. Special Struct

ÉÏÎÄÌáµ½»á°ÑÒª¸²¸ÇµÄ·½·¨Ö¸Ïò_objc_msgForward£¬½øÐÐת·¢²Ù×÷£¬ÕâÀï³öÏÖÒ»¸öÎÊÌ⣬Èç¹ûÌæ»»·½·¨µÄ·µ»ØÖµÊÇijЩ struct£¬Ê¹Óà _objc_msgForward£¨»òÕß֮ǰµÄ @selector(__JPNONImplementSelector)£©»á crash¡£¼¸¾­Õ·×ª£¬ÕÒµ½Á˽â¾ö·½·¨£º¶ÔÓÚijЩ¼Ü¹¹Ä³Ð© struct£¬±ØÐëʹÓà _objc_msgForward_stret ´úÌæ _objc_msgForward¡£ÎªÊ²Ã´ÒªÓà _objc_msgForward_stret ÄØ£¬ÕÒµ½Ò»ÆªËµÃ÷ objc_msgSend_stret ºÍ objc_msgSend Çø±ðµÄÎÄÕ£ºhttp://sealiesoftware.com/blog/archive/2008/10/30/objcexplainobjcmsgSendstret.html£©£¬ËµµÃ±È½ÏÇå³þ£¬Ô­ÀíÊÇÒ»ÑùµÄ£¬ÊÇCµÄһЩµ×²ã»úÖÆµÄÔ­Òò£¬¼òµ¥¸´Êöһϣº

´ó¶àÊý CPU ÔÚÖ´ÐÐ C º¯Êýʱ»á°Ñǰ¼¸¸ö²ÎÊý·Å½ø¼Ä´æÆ÷À¶Ô obj_msgSend À´ËµÇ°Á½¸ö²ÎÊý¹Ì¶¨ÊÇ self / _cmd£¬ËüÃÇ»á·ÅÔڼĴæÆ÷ÉÏ£¬ÔÚ×îºóÖ´ÐÐÍêºó·µ»ØÖµÒ²»á±£´æÔڼĴæÆ÷ÉÏ£¬È¡Õâ¸ö¼Ä´æÆ÷µÄÖµ¾ÍÊÇ·µ»ØÖµ£º

-(int) method:(id)arg;  
r3 = self
r4 = _cmd, @selector(method:)
r5 = arg
(on exit) r3 = returned int

ÆÕͨµÄ·µ»ØÖµ(int/pointer)ºÜС£¬·ÅÔڼĴæÆ÷ÉÏûÎÊÌ⣬µ«ÓÐЩ struct ÊǺܴóµÄ£¬¼Ä´æÆ÷·Å²»Ï£¬ËùÒÔÒªÓÃÁíÒ»ÖÖ·½Ê½£¬ÔÚÒ»¿ªÊ¼ÉêÇëÒ»¶ÎÄڴ棬°ÑÖ¸Õë±£´æÔڼĴæÆ÷ÉÏ£¬·µ»ØÖµÍùÕâ¸öÖ¸ÕëÖ¸ÏòµÄÄÚ´æÐ´Êý¾Ý£¬ËùÒԼĴæÆ÷ÒªÌÚ³öÒ»¸öλÖ÷ÅÕâ¸öÖ¸Õ룬self / _cmd ÔڼĴæÆ÷µÄλÖþͱäÁË£º

-(struct st) method:(id)arg;  
r3 = &struct_var (in caller's stack frame)
r4 = self
r5 = _cmd, @selector(method:)
r6 = arg
(on exit) return value written into struct_var

²»ÖªµÀ self / _cmd µÄλÖñäÁË£¬ËùÒÔÒªÓÃÁíÒ»¸ö·½·¨ objc_msgSend_stret ´úÌæ¡£Ô­Àí´ó¸Å¾ÍÊÇÕâÑù¡£
ÉÏÃæËµÄ³Ð©¼Ü¹¹Ä³Ð© struct ÓÐÎÊÌ⣬ÄǾßÌåÊÇÄÄÐ©ÄØ£¿iOS ¼Ü¹¹ÖÐ·Ç arm64 µÄ¶¼ÓÐÕâÎÊÌ⣬¶øÔõÑùµÄ struct ÐèÒª×ßÉÏÊöÁ÷³ÌÓà xxx_stret ´úÌæÔ­·½·¨ÔòûÓÐÃ÷È·µÄ¹æÔò£¬OC ҲûÓÐÌṩ½Ó¿Ú£¬Ö»ÓÐÔÚÒ»¸öÆæÝâµÄ½Ó¿ÚÉÏ͸¶ÁËÕâ¸öÌì»ú£¬ÓÚÊÇÓÐÕâÑùÒ»¸öÉñÆæµÄÅжϣº

if ([methodSignature.debugDescription rangeOfString:
@"is special struct return? YES"].location != NSNotFound)

ÔÚ NSMethodSignature µÄ debugDescription ÉÏ´ò³öÁËÊÇ·ñ special struct£¬Ö»ÄÜͨ¹ýÕâ×Ö·û´®Åжϡ£ËùÒÔ×îÖյĴ¦ÀíÊÇ£¬ÔÚ·Ç arm64 Ï£¬ÊÇ special struct ¾Í×ß _objc_msgForward_stret£¬·ñÔò×ß _objc_msgForward¡£

2. ÄÚ´æÎÊÌâ

i. Double Release

ʵÏÖ¹ý³ÌÖÐÅöµ½Ò»Ð©ÄÚ´æÎÊÌ⣬Ê×ÏÈÊÇ Double Release ÎÊÌâ¡£´Ó -forwardInvocation: ÀïµÄ NSInvocation ¶ÔÏóÈ¡²ÎÊýֵʱ£¬Èô²ÎÊýÖµÊÇidÀàÐÍ£¬ÎÒÃÇ»áÕâÑùÈ¡:

id arg;  
[invocation getArgument:&arg atIndex:i];

µ«ÕâÑùµÄд·¨»áµ¼Ö crash£¬ÕâÊÇÒòΪ id arg ÔÚARCÏÂÏ൱ÓÚ __strong id arg£¬ÈôÕâʱÔÚ´úÂëÏÔʽΪ arg ¸³Öµ£¬¸ù¾Ý ARC µÄ»úÖÆ£¬»á×Ô¶¯²åÈëÒ»Ìõ retain Óï¾ä£¬È»ºóÔÚÍ˳ö×÷ÓÃÓòʱ²åÈë release Óï¾ä£º

- (void)method {  
id arg = [SomeClass getSomething];
// [arg retain]
...
// [arg release] Í˳ö×÷ÓÃÓòǰrelease
}

µ«ÎÒÃÇÕâÀï²»ÊÇÏÔʽ¶Ô arg ½øÐи³Öµ£¬¶øÊÇ´«Èë -getArgument:atIndex: ·½·¨£¬ÔÚÕâÀïÃæ¸³Öµºó ARC ûÓÐ×Ô¶¯¸øÕâ¸ö±äÁ¿²åÈë retain Óï¾ä£¬µ«Í˳ö×÷ÓÃÓòʱ»¹ÊÇ×Ô¶¯²åÈëÁË release Óï¾ä£¬µ¼ÖÂÕâ¸ö±äÁ¿¶àÊÍ·ÅÁËÒ»´Î£¬µ¼Ö crash¡£½â¾ö·½·¨ÊÇ°Ñ arg ±äÁ¿Éè³É _unsafeunretained »ò __weak£¬Èà ARC ²»ÔÚËüÍ˳ö×÷ÓÃÓòʱ²åÈë release Óï¾ä¼´¿É£º

__unsafe_unretained id arg;  
[invocation getReturnValue:&arg];

»¹¿ÉÒÔͨ¹ý __bridge ת»»Èþֲ¿±äÁ¿³ÖÓзµ»Ø¶ÔÏó£¬ÕâÑù×öÒ²ÊÇûÎÊÌâµÄ£º

id returnValue;  
void *result;
[invocation getReturnValue:&result];
returnValue = (__bridge id)result;

ii. ÄÚ´æÐ¹Â¶

Double Release µÄÎÊÌâ½â¾öÁË£¬ÓÖÅöµ½ÄÚ´æÐ¹Â¶µÄ¿Ó¡£Ä³Ìì github issue ÉÏÓÐÈËÌá¶ÔÏóÉú³ÉºóûÓÐÊÍ·Å£¬¼¸¾­ÅŲ飬¶¨Î»µ½»¹ÊÇÕâÀï NSInvocation getReturnValue µÄÎÊÌ⣬µ± NSInvocation µ÷ÓõÄÊÇ alloc ʱ£¬·µ»ØµÄ¶ÔÏó²¢²»»áÊÍ·Å£¬Ôì³ÉÄÚ´æÐ¹Â¶£¬Ö»Óаѷµ»Ø¶ÔÏóµÄÄÚ´æ¹ÜÀíÈ¨ÒÆ½»³öÀ´£¬ÈÃÍⲿ¶ÔÏó°ïËüÊͷŲÅÐУº

id returnValue; void *result; [invocation getReturnValue:&result];  
if ([selectorName isEqualToString:@"alloc"] ||
[selectorName isEqualToString:@"new"])
{ returnValue = (__bridge_transfer id)result; }
else { returnValue = (__bridge
id)result; }

ÕâÊÇÒòΪ ARC ¶Ô·½·¨ÃûÓÐÔ¼¶¨£¬µ±·½·¨Ãû¿ªÍ·ÊÇ alloc / new / copy / mutableCopy ʱ£¬·µ»ØµÄ¶ÔÏóÊÇ retainCount = 1 µÄ£¬³ý´ËÖ®Í⣬·½·¨·µ»ØµÄ¶ÔÏó¶¼ÊÇ autorelease µÄ£¬°´ÉÏÒ»½ÚµÄ˵·¨£¬¶ÔÓÚÆÕͨ·½·¨·µ»ØÖµ£¬ARC »áÔÚ¸³¸ø strong ±äÁ¿Ê±×Ô¶¯²åÈë retain Óï¾ä£¬µ«¶ÔÓÚ alloc µÈÕâЩ·½·¨£¬²»»áÔÙ×Ô¶¯²åÈë retain Óï¾ä£º

id obj = [SomeObject alloc];  
//alloc ·½·¨·µ»ØµÄ¶ÔÏó retainCount ÒÑ +1£¬ÕâÀï²»ÐèÒªretain
id obj2 = [SomeObj someMethod];
//·½·¨·µ»ØµÄ¶ÔÏóÊÇ autorelease£¬ARC »áÔÙÕâÀï×Ô¶¯²åÈë [obj2 retain] Óï¾ä

¶ø ARC ²¢Ã»Óд¦Àí·ÇÏÔʾµ÷ÓÃʱµÄÇé¿ö£¬ÕâÀﶯ̬µ÷ÓÃÕâЩ·½·¨Ê±£¬ARC ¶¼²»»á×Ô¶¯²åÈë retain£¬ÕâÖÖÇé¿öÏ£¬alloc / new µÈÕâÀà·½·¨·µ»ØÖµµÄ retainCount ÊÇ»á±ÈÆäËû·½·¨·µ»ØÖµ¶à1µÄ£¬ËùÒÔÐèÒªÌØÊâ´¦ÀíÕâÀà·½·¨¡£

3. ¡®_¡¯µÄ´¦Àí

JSPatch ÓÃÏ»®Ïß¡¯¡¯Á¬½ÓOC·½·¨¶à¸ö²ÎÊý¼äµÄ¼ä¸ô£º

- (void)setObject:(id)anObject forKey:(id)aKey;  
<==>
setObject_forKey()

setObject_forKey()
ÄÇÈç¹ûOC·½·¨ÃûÀﺬÓÐ'_'£¬ÄǾͳöÏÖÆçÒåÁË£º

<code>- (void)set_object:(id)anObject forKey:(id)aKey;  
<==>
set_object_forKey()</code>!


û·¨ÖªµÀ set_object_forKey ¶ÔÓ¦µÄ selector ÊÇ set_object:forKey: »¹ÊÇ set:object:forKey:¡£
¶Ô´ËÐèÒª¶¨¸ö¹æÔò£¬ÔÚ JS ÓÃÆäËû×Ö·û´úÌæ OC ·½·¨ÃûÀïµÄ _¡£JS ÃüÃû¹æÔò³ýÁË×ÖĸºÍÊý×Ö£¬¾ÍÖ»ÓÐ $ ºÍ _£¬¿´ÆðÀ´Ö»ÄÜÓà $ ´úÌæÁË£¬µ«Ð§¹ûºÜ³ó£º

- (void)set_object:(id)anObject forKey:(id)aKey;  
- (void)_privateMethod();
<==>
set$object_forKey()
$privateMethod()

ÓÚÊdz¢ÊÔÁíÒ»ÖÖ·½·¨£¬ÓÃÁ½¸öÏ»®Ïß __ ´úÌæ£º

set__object_forKey() __privateMethod()  

µ«ÓÃÁ½¸öÏ»®Ïß´úÌæÓиöÎÊÌ⣬OC ·½·¨Ãû²ÎÊýºóÃæ¼ÓÏ»®Ïß»áÆ¥Åä²»µ½

- (void)setObject_:(id)anObject forKey:(id)aKey;  
<==>
setObject___forKey()

ʵ¼ÊÉÏ setObject___forKey() Æ¥Åäµ½¶ÔÓ¦µÄ selector ÊÇ setObject:_forKey:¡£ËäÈ»ÓÐÕâ¸ö¿Ó£¬µ«ÒòΪºÜÉÙ¼ûµ½ÕâÖÖÆæÝâµÄÃüÃû·½Ê½£¬¸Ð¾õÎÊÌâ²»´ó£¬Ê¹ÓÃ$Ò²»áµ¼ÖÂÌæ»»²»ÁË OC ·½·¨Ãû°üº¬ $ ×Ö·ûµÄ£¬×îÖÕΪÁË´úÂëÑÕÖµ£¬Ê¹ÓÃÁË˫ϻ®Ïß __ ±íʾ¡£

4.JPBoxing

ÔÚʹÓà JSPatch ¹ý³ÌÖз¢ÏÖJSÎÞ·¨µ÷Óà NSMutableArray / NSMutableDictionary / NSMutableString µÄ·½·¨È¥ÐÞ¸ÄÕâЩ¶ÔÏóµÄÊý¾Ý£¬ÒòΪÕâÈýÕß¶¼ÔÚ´Ó OC ·µ»Øµ½ JS ʱ JavaScriptCore °ÑËüÃÇת³ÉÁË JS µÄ Array / Object / String£¬ÔÚ·µ»ØµÄʱºò¾ÍÍÑÀëÁ˸úÔ­¶ÔÏóµÄÁªÏµ£¬Õâ¸öת»»ÔÚ JavaScriptCore ÀïÊÇÇ¿ÖÆ½øÐеģ¬ÎÞ·¨Ñ¡Ôñ¡£

ÈôÏëÒªÔÚ¶ÔÏó·µ»Ø JS ºó£¬»Øµ½ OC »¹Äܵ÷ÓÃÕâ¸ö¶ÔÏóµÄ·½·¨£¬¾ÍÒª×èÖ¹ JavaScriptCore µÄת»»£¬Î¨Ò»µÄ·½·¨¾ÍÊDz»Ö±½Ó·µ»ØÕâ¸ö¶ÔÏ󣬶øÊǶÔÕâ¸ö¶ÔÏó½øÐзâ×°£¬JPBoxing ¾ÍÊÇ×öÕâ¸öÊÂÇéµÄ£º

@interface JPBoxing : NSObject  
@property (nonatomic) id obj;
@end

@implementation JPBoxing
+ (instancetype)boxObj:(id)obj
{
JPBoxing *boxing = [[JPBoxing alloc] init];
boxing.obj = obj;
return boxing;
}

°Ñ NSMutableArray / NSMutableDictionary / NSMutableString ¶ÔÏó×÷Ϊ JPBoxing µÄ³ÉÔ±±£´æÔÚ JPBoxing ʵÀý¶ÔÏóÉÏ·µ»Ø¸ø JS£¬JS Äõ½µÄÊÇ JPBoxing ¶ÔÏóµÄÖ¸Õ룬ÔÙ´«»Ø¸ø OC ʱ¾Í¿ÉÒÔͨ¹ý¶ÔÏó³ÉԱȡµ½Ô­À´µÄ NSMutableArray / NSMutableDictionary / NSMutableString ¶ÔÏó£¬ÀàËÆÓÚ×°Ïä/²ðÏä²Ù×÷£¬ÕâÑù¾Í±ÜÃâÁËÕâЩ¶ÔÏó±» JavaScriptCore ת»»¡£
ʵ¼ÊÉÏÖ»ÓпɱäµÄ NSMutableArray / NSMutableDictionary / NSMutableString ÕâÈý¸öÀàÓбØÒªµ÷ÓÃËüµÄ·½·¨È¥Ð޸ĶÔÏóÀïµÄÊý¾Ý£¬²»¿É±äµÄ NSArray / NSDictionary / NSString ÊÇû±ØÒªÕâÑù×öµÄ£¬Ö±½ÓתΪ JS ¶ÔÓ¦µÄÀàÐÍʹÓÃÆðÀ´»á¸ü·½±ã£¬µ«ÎªÁ˹æÔò¼òµ¥£¬JSPatch Èà NSArray / NSDictionary / NSString ҲͬÑùÒÔ·â×°µÄ·½Ê½·µ»Ø£¬±ÜÃâÔÚµ÷Óà OC ·½·¨·µ»Ø¶ÔÏóʱ»¹ÐèÒª¹ØÐÄËü·µ»ØµÄÊǿɱ仹ÊDz»¿É±ä¶ÔÏó¡£×îºóÕû¸ö¹æÔò»¹ÊÇͦÇåÎú£ºNSArray / NSDictionary / NSString ¼°Æä×ÓÀàÓëÆäËû NSObject ¶ÔÏóµÄÐÐΪһÑù£¬ÔÚ JS ÉÏÄõ½µÄ¶¼Ö»ÊÇÆä¶ÔÏóÖ¸Õ룬¿ÉÒÔµ÷ÓÃËüÃÇµÄ OC ·½·¨£¬ÈôÒª°ÑÕâÈýÖÖ¶ÔÏóתΪ¶ÔÓ¦µÄ JS ÀàÐÍ£¬Ê¹ÓöîÍâµÄ .toJS() µÄ½Ó¿Úȥת»»¡£

¶ÔÓÚ²ÎÊýºÍ·µ»ØÖµÊÇCÖ¸ÕëºÍ Class ÀàÐ͵ÄÖ§³ÖͬÑùÊÇÓà JPBoxing ·â×°µÄ·½Ê½£¬°ÑÖ¸ÕëºÍ Class ×÷Ϊ³ÉÔ±±£´æÔÚ JPBoxing ¶ÔÏóÉÏ·µ»Ø¸ø JS£¬´«»Ø OC ʱÔÙ½â³öÀ´Äõ½Ô­À´µÄÖ¸ÕëºÍ Class£¬ÕâÑù JSPatch ¾ÍÖ§³ÖËùÓÐÊý¾ÝÀàÐÍ OC<->JS µÄ»¥´«ÁË¡£

5. nilµÄ´¦Àí

i. Çø·ÖNSNull/nil

¶ÔÓÚ"¿Õ"µÄ±íʾ£¬JS ÓÐ null / undefined£¬OC ÓÐ nil / NSNull£¬JavaScriptCore ¶ÔÕâЩ²ÎÊý´«µÝ´¦ÀíÊÇÕâÑùµÄ£º

´Ó JS µ½ OC£¬Ö±½Ó´«µÝ null / undefined µ½ OC ¶¼»áתΪ nil£¬Èô´«µÝ°üº¬ null / undefined µÄ Array ¸ø OC£¬»áתΪ NSNull¡£
´Ó OC µ½ JS£¬nil »áתΪ null£¬NSNull ÓëÆÕͨ NSObject Ò»Ñù·µ»ØÖ¸Õë¡£
JSPatch µÄÁ÷³ÌÉ϶¼ÊÇͨ¹ýÊý×éµÄ·½Ê½°Ñ²ÎÊý´Ó JS ´«Èë OC£¬ÕâÑùËùÓÐµÄ null / undefined µ½ OC ¾Í¶¼±ä³ÉÁË NSNull£¬¶øÕæÕýµÄ NSNull ¶ÔÏó´«½øÀ´Ò²ÊÇ NSNull£¬ÎÞ·¨·Ö±æ´Ó JS ¹ýÀ´Êµ¼Ê´«µÄÊÇʲô£¬ÐèÒªÓÐÖÖ·½Ê½Çø·ÖÕâÁ½Õß¡£

¿¼ÂǹýÔÚ JS ÓÃÒ»¸öÌØÊâµÄ¶ÔÏó´ú±í nil£¬null / undefined Ö»ÓÃÀ´±íʾ NSNull£¬ºóÀ´¾õµÃ NSNull ÊǺÜÉÙÊÖ¶¯´«µÝµÄ±äÁ¿£¬¶ø null / undefined ÒÔ¼° OC µÄ nil È´ºÜ³£¼û£¬ÕâÑù×ö»á¸øÈÕ³£¿ª·¢´øÀ´ºÜ´ó²»±ã¡£ÓÚÊÇ·´¹ýÀ´£¬ÔÚ JS ÓÃÒ»¸öÌØÊâ±äÁ¿ nsnull ±íʾ NSNull£¬ÆäËû null / undefined ±íʾ nil£¬ÕâÑù´«Èë OC ¾Í¿ÉÒÔ·Ö±æ³ö nil ºÍ NSNull£¬¾ßÌåʹÓ÷½Ê½£º

@implementation JPObject  
+ (void)testNil:(id)obj
{
NSLog(@"%@", obj);
}
@end

require("JPObject").testNil(null) //output: nil
require("JPObject").testNil(nsnull) //output: NSNull

ÕâÑù×öÓиöС¿Ó£¬¾ÍÊÇÏÔʾʹÓà NSNull.null() ×÷Ϊ²ÎÊýµ÷ÓÃʱ£¬µ½ OC ºó»á±ä³É nil£º

require("JPObject").testNil(require("NSNull").null()) //output: nil  

Õâ¸öÖ»Ðè×¢ÒâÏÂÓà nsnull ´úÌæ¾ÍÐУ¬´Ó OC ·µ»ØµÄ NSNull Ôٻش«»ØÈ¥»¹ÊÇ¿ÉÒÔʶ±ðµ½ NSNull¡£

ii.Á´Ê½µ÷ÓÃ

µÚ¶þ¸öÎÊÌ⣬nil ÔÚ JS ÀïÓà null / undefined ±íʾ£¬Ôì³ÉµÄºó¹ûÊÇÎÞ·¨Óà nil µ÷Ó÷½·¨£¬Ò²¾ÍÎÞ·¨±£Ö¤Á´Ê½µ÷Óõݲȫ£º

@implementation JPObject + (void)returnNil { return nil; }
 @end [[JPObject  
returnNil] hash] //it¡¯s
OK require("JPObject").returnNil().hash() //crash

Ô­ÒòÊÇÔÚ JS Àï null / undefined ²»ÊǶÔÏó£¬ÎÞ·¨µ÷ÓÃÈκη½·¨£¬°üÀ¨ÎÒÃǸøËùÓжÔÏó¼ÓµÄ __c() ·½·¨¡£½â¾ö·½Ê½Ò»¶È¾õµÃÖ»Óлص½ÉÏÃæËµµÄ£¬ÓÃÒ»¸öÌØÊâµÄ¶ÔÏó±íʾ nil£¬²ÅÄܽâ¾öÕâ¸öÎÊÌâÁË¡£µ«Ê¹ÓÃÌØÊâµÄ¶ÔÏó±íʾ nil£¬ºó¹û¾ÍÊÇÔÚ js ÅжÏÊÇ·ñΪ nil ʱ¾ÍÒªºÜ†ªà£º

//¼ÙÉèÓÃÒ»¸ö_nil¶ÔÏó±äÁ¿±íʾOC·µ»ØµÄnil  
var obj = require("JPObject").returnNil()
obj.hash() //¾­¹ýÌØÊâ´¦ÀíûÎÊÌâ
if (!obj || obj == _nil) {
//Åж϶ÔÏóÊÇ·ñΪnil¾ÍµÃ¸½¼ÓÅжÏÊÇ·ñµÈÓÚ_nil
}

ÕâÑùµÄʹÓ÷½Ê½ÄÑÒÔ½ÓÊÜ£¬¼ÌÐøÑ°ÕÒ½â¾ö·½°¸£¬·¢ÏÖ true / false ÔÚ JS ÊǸö¶ÔÏó£¬ÊÇ¿ÉÒÔµ÷Ó÷½·¨µÄ£¬Èç¹ûÓà false ±íʾ nil£¬¼´¿ÉÒÔ×öµ½µ÷Ó÷½·¨£¬ÓÖ¿ÉÒÔÖ±½Óͨ¹ý if (!obj) ÅжÏÊÇ·ñΪ nil£¬ÓÚÊÇÑØ×ÅÕâ¸ö·½Ïò£¬½â¾öÁËÓà false ±íʾ nil ´øÀ´µÄ¸÷ÖÖ¿Ó£¬¼¸ºõÍêÃÀµØ½â¾öÁËÕâ¸öÎÊÌ⡣ʵÏÖÉϵÄϸ½Ú¾Í²»¶à˵ÁË£¬Ëµ"¼¸ºõÍêÃÀ"£¬ÊÇÒòΪ»¹ÓÐÒ»¸öС¿Ó£¬´«µÝ false ¸ø OC ÉϲÎÊýÀàÐÍÊÇ NSNumber* µÄ·½·¨£¬OC »áµÃµ½ nil ¶ø²»ÊÇ NSNumber ¶ÔÏó£º

@implementation JPObject + (void)passNSNumber:(NSNumber *)num { NSLog(@"%@",  
num); } @end require("JPObject").passNSNumber(false) //output: nil

Èç¹û OC ·½·¨µÄ²ÎÊýÀàÐÍÊÇ BOOL£¬»òÕß´«ÈëµÄÊÇ true / 0£¬¶¼ÊÇûÎÊÌâµÄ£¬ÕâС¿ÓÎÞÉË´óÑÅ¡£

ÌâÍâ»°£¬ÉñÆæµÄ JS Àï false µÄ this ¾¹È»²»ÔÙÊÇÔ­À´µÄ false£¬¶øÊÇÁíÒ»¸ö Boolean ¶ÔÏó£¬Ì«ÌØÊâÁË£º

Object.prototype.c = function(){console.log(this === false)};  
false.c() //output false

×ܽá

JSPatchµÄÔ­ÀíÒÔ¼°Ò»Ð©ÊµÏÖϸ½Ú¾Í²ûÊöµ½ÕâÀϣÍûÕâÆªÎÄÕ¶Դó¼ÒÁ˽âºÍʹÓà JSPatch ÓаïÖú¡£

   
2500 ´Îä¯ÀÀ       27
Ïà¹ØÎÄÕ Ïà¹ØÎĵµ Ïà¹Ø¿Î³Ì



Éî¶È½âÎö£ºÇåÀíÀôúÂë
ÈçºÎ±àд³öÓµ±§±ä»¯µÄ´úÂë
ÖØ¹¹-ʹ´úÂë¸ü¼ò½àÓÅÃÀ
ÍŶÓÏîÄ¿¿ª·¢"±àÂë¹æ·¶"ϵÁÐÎÄÕÂ
ÖØ¹¹-¸ÄÉÆ¼ÈÓдúÂëµÄÉè¼Æ
Èí¼þÖØ¹¹v2
´úÂëÕû½àÖ®µÀ
¸ßÖÊÁ¿±à³Ì¹æ·¶
»ùÓÚHTML5¿Í»§¶Ë¡¢Web¶ËµÄÓ¦Óÿª·¢
HTML 5+CSS ¿ª·¢
ǶÈëʽC¸ßÖÊÁ¿±à³Ì
C++¸ß¼¶±à³Ì
×îл¼Æ»®
DeepSeekÔÚÈí¼þ²âÊÔÓ¦ÓÃʵ¼ù 4-12[ÔÚÏß]
DeepSeek´óÄ£ÐÍÓ¦Óÿª·¢Êµ¼ù 4-19[ÔÚÏß]
UAF¼Ü¹¹ÌåϵÓëʵ¼ù 4-11[±±¾©]
AIÖÇÄÜ»¯Èí¼þ²âÊÔ·½·¨Óëʵ¼ù 5-23[ÉϺ£]
»ùÓÚ UML ºÍEA½øÐзÖÎöÉè¼Æ 4-26[±±¾©]
ÒµÎñ¼Ü¹¹Éè¼ÆÓ뽨ģ 4-18[±±¾©]

AndroidÊÖ»ú¿ª·¢£¨Ò»£©
Àí½âJavascript
·ÇµäÐÍajaxʵ¼ù
³¹µ×µÄAjax
javascript ʹÓÃCookies
ʹÓà jQuery ¼ò»¯ Ajax ¿ª·¢

Struts+Spring+Hibernate
»ùÓÚJ2EEµÄWeb 2.0Ó¦Óÿª·¢
J2EEÉè¼ÆÄ£Ê½ºÍÐÔÄܵ÷ÓÅ
Java EE 5ÆóÒµ¼¶¼Ü¹¹Éè¼Æ
Javaµ¥Ôª²âÊÔ·½·¨Óë¼¼Êõ
Java±à³Ì·½·¨Óë¼¼Êõ

ijº½¿Õ¹«Ë¾IT²¿ JavaScriptʵ¼ù
ijµçÊÓÈí¼þ HTML5ºÍJavaScript
Öк½ÐÅ JavaScript¸ß¼¶Ó¦Óÿª·¢
´óÇìÓÍÌï web½çÃæAjax¿ª·¢¼¼Êõ
ºÍÀûʱ ʹÓÃAJAX½øÐÐWEBÓ¦Óÿª·¢