Introduced
Jspatch is a tool for hot fixes introduced by bang in 2015, so long as a minimal jspatch engine is introduced into the project, it is possible to invoke and replace any objective-c native methods with JavaScript, gain scripting language capabilities < update apps dynamically , replace the project native code repair bug>.
The author has commercialized Jspatch, provided scripts for background hosting, versioning, and secure transport, all with the introduction of an SDK (+startwithappkey:). Jspatch Platform
Implementation principle
The most fundamental reason for jspatch to invoke and rewrite the OC method via JS is that objective-c is a dynamic language, and the generation of all calls/classes for all methods on OC is performed at runtime through Objective-c runtime, via Apple's Jave in iOS7 Scriptcore.framework to parse JavaScript scripts, bridge with OBJECTIVE-C code, take advantage of runtime features, let apps have hit code push capability
Concrete implementation principle the author has given, no longer a cumbersome description, please see here
How to use
The specific use of the method here is described in detail, here is about the process </br>
From the GitHub jspatch file, copy the entire Jspatch folder to the project, import JPEngine.h
, invoke the [JPEngine startEngine]
Jspatch engine, and [JPEngine evaluateScript:@"..."]
Interface to execute JavaScript statements. Personally think that the grammar of Jspatch do not deliberately to see, in the process of writing stuck to the author's original text to find.
[Jpengine StartEngine];//directly execute JS[Jpengine Evaluatescript:@"var Alertview = require (' Uialertview '). Alloc (). Init (); Alertview.settitle (' Alert '); Alertview.setmessage (' Alertview from JS '); Alertview.addbuttonwithtitle (' OK '); Alertview.show (); "];//pull back the JS script from the network execution (key to implementing the hot fix)[Nsurlconnection sendasynchronousrequest:[nsurlrequest Requestwithurl:[nsurl urlwithstring:@"Http://cnbang.net/test.js"]] Queue:[nsoperationqueue Mainqueue] completionhandler:^ (nsurlresponse *response, NSData *data, NSError *connectionerror) {NSString*script =[[NSString alloc] Initwithdata:data encoding:nsutf8stringencoding]; [Jpengine evaluatescript:script];}];//Execute local JS fileNSString *sourcepath = [[NSBundle mainbundle] Pathforresource:@"Sample"OfType:@"JS"]; NSString*script =[NSString Stringwithcontentsoffile:sourcepath encoding:nsutf8stringencoding Error:nil]; [Jpengine Evaluatescript:script];
Basic usage of javescript (excerpt from Bang):
//call require to introduce the OC class to be usedRequire'UIView, Uicolor, UISlider, Nsindexpath')//Calling class methodsvarRedcolor =Uicolor.redcolor ();//Invoking instance methodsvarView =Uiview.alloc (). Init (); View.setneedslayout ();//Set ProertyView.setbackgroundcolor (redcolor);//Get PropertyvarBgColor =View.backgroundcolor ();//Multi-parameter method names are separated by ' _ '://Oc:nsindexpath *indexpath = [Nsindexpath indexpathforrow:0 insection:1];varIndexpath = Nsindexpath.indexpathforrow_insection (0,1);//method Name contains underscore ' _ ', JS is represented by double underline//OC: [Jpobject _privatemethod];Jpobject.__privatemethod ()//If you want to convert ' nsarray '/' nsstring '/' nsdictionary ' to the corresponding JS type, use '. TOJS () ' interface.varArr = require ('Nsmutablearray'). Alloc (). Init () Arr.addobject ("JS") Jsarr=Arr.tojs () console.log (Jsarr.push ("Patch"). Join ("'))//Output:jspatch//in the way JS uses a dictionary to represent Cgrect/cgsize/cgpoint/nsrangevarview = Uiview.alloc (). initWithFrame ({x: -Y: -, Width: -, Height: -});varx =view.bounds (). x;//when a block is passed into objective-c from JavaScript, it needs to write the type of each parameter. //OC Method: + (void) Request: (void (^) (NSString *content, BOOL success)) CallbackRequire'Jpobject'). Request (Block ("NSString *, BOOL", function (CTN, succ) {if(SUCC) log (CTN)});//GCDDispatch_after (Function (1.0, function () {//Do something})) Dispatch_async_main (function () {//Do something})
A simple example of using Javescript:
//APPDELEGATE.M#import"AppDelegate.h"#import"HBJSPatchMainViewController.h"#import"JPEngine.h"@interface appdelegate () @end @implementation appdelegate-(BOOL) Application: (UIApplication *) application didfinishlaunchingwithoptions: (Nsdictionary *) launchoptions {[Jpengine startengine]; //Start engineNSString *sourcepath = [[NSBundle mainbundle] Pathforresource:@"Demo"OfType:@"JS"]; NSString*script = [NSString stringwithcontentsoffile:sourcepath encoding:nsutf8stringencoding Error:nil];//read JS from local[Jpengine Evaluatescript:script];//Execute JS StatementSelf.window=[[UIWindow Alloc]initwithframe:[uiscreen mainscreen].bounds]; Self.window.rootViewController=[[Uinavigationcontroller Alloc]initwithrootviewcontroller:[[hbjspatchmainviewcontroller alloc]init]; [Self.window makekeyandvisible]; returnYES;} @end//VIEWCONTROLLER.M#import"HBJSPatchMainViewController.h"@interface Hbjspatchmainviewcontroller () @end @implementation Hbjspatchmainviewcontroller- (void) viewdidload {[Super viewdidload];![Uploading jspatch_353937.gif ...] UIButton*button =[UIButton Buttonwithtype:uibuttontypesystem]; Button.frame= CGRectMake (0,0, $, -); Button.center=Self.view.center; Button.backgroundcolor=[Uicolor Orangecolor]; [Button Settitle:@"into the JS generated UI interface"Forstate:uicontrolstatenormal]; [Button Settitlecolor:[uicolor Whitecolor] forstate:uicontrolstatenormal]; [Button addtarget:self action: @selector (Buttontouch:) forcontrolevents:uicontroleventtouchupinside]; [Self.view Addsubview:button]; Self.view.backgroundColor=[Uicolor Bluecolor]; }- (void) Buttontouch: (UIButton *) button {//The triggering method is in the demo. JS in} @end//HBJSPATCHTSETVIEWCONTROLLER.M#import"HBJSPatchTsetViewController.h"@interface Hbjspatchtsetviewcontroller () @end @implementation Hbjspatchtsetviewcontroller- (void) viewdidload {[Super viewdidload]; UILabel*lable = [[UILabel alloc] Initwithframe:cgrectmake (0,0, -, -)]; Lable.center=Self.view.center; Lable.textalignment=Nstextalignmentcenter; Lable.text=@"js to native UI"; [Self.view addsubview:lable]; Self.view.backgroundColor=[Uicolor Whitecolor]; } @end//demo.js File//Button EventsDefineClass ('Hbjspatchmainviewcontroller', {//which class is addressed toButtontouch:function (Button) {//overriding methods in a class//Jump to TableView varTableviewctrl =Hbtableviewcontroller.alloc (). Init () Self.navigationcontroller (). pushviewcontroller_animated (TableViewCtrl , YES)}}) DefineClass ('Hbtableviewcontroller:uitableviewcontroller', {//to create a class and implement a method in a classdatasource:function () {//Jspatch can add member variables dynamically to an object by-getprop:,-setprop:forkey: These two methods. vardata = Self.getprop ('Data') if(data)returndata; vardata = []; for(vari =0; I < -; i + +) {Data.push ("cell created by JS"+i); } self.setprop_forkey (Data,'Data') returndata; }, Numberofsectionsintableview:function (TableView) {return 1; }, Tableview_numberofrowsinsection:function (TableView, section) {returnSelf.datasource (). Count (); }, Tableview_cellforrowatindexpath:function (TableView, Indexpath) {varCell = Tableview.dequeuereusablecellwithidentifier ("Cell") if(!cell) {Cell= Require ('UITableViewCell'). Alloc (). Initwithstyle_reuseidentifier (0,"Cell")} cell.textlabel (). SetText (Self.datasource (). Objectatindex (Indexpath.row ()))returncell}, Tableview_heightforrowatindexpath:function (TableView, Indexpath) {return -}, Tableview_didselectrowatindexpath:function (TableView, Indexpath) { /c0>//jump to native UI varTestviewcontroller = require ('Hbjspatchtsetviewcontroller'). Alloc (). Init () Self.navigationcontroller (). pushviewcontroller_animated (Testviewcontroller, YES) },})
Example diagram
Usually we put the execution of the script in the Appdelegate didfinishlaunchingwithoptions: method, the personal proposal to use a management tool Class (manager) to manage the script download and execution, Can be used to set a script download interval time and local patches to detect and so on
For more usage please click here
Security issues
Because JS script can arbitrarily call OC method, modify OC file, the permissions are very large, if the person attacked to replace the code, it will cause great harm. In general, we should encrypt the JS file after it is submitted to the background, it is recommended RSA and HTTPS to ensure security, and I will fill in the encrypted article later, Interested please pay attention to me, here first recommended this article: Jspatch Deploy security Policy
Thinking
- Now that the Apple AppStore audit cycle has become a day, making bug repair quickly, small companies also need to increase labor costs to achieve heat repair?
使用JSPatch的重中之重就是安全问题,虽然可以人为的进行加密传输,但总是有风险,而只要一出现问题都会是重大的问题
- In a very complex method, only the middle of a line of code needs to be modified, the whole method with JS rewrite, recommend the author developed objective-c JavaScript code tool Jspatch Convertor, but some of the complex syntax is still to be manually modified
- When using Jspatch to resolve the online bug, should be in the next version of the OC code to modify the bug in the project, should not allow the patch code to persist more than one version, if after Jspatch stop maintenance, will not have a serious impact
Jspatch-Basic use and learning