Skip to content

JSPatch bridge Objective-C and Javascript using the Objective-C runtime. You can call any Objective-C class and method in JavaScript by just including a small engine. JSPatch is generally used to hotfix iOS App.

License

Notifications You must be signed in to change notification settings

bang590/JSPatch

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

JSPatch

TravisCocoaPods VersionLicense

中文介绍 | 文档 | JSPatch平台

请大家不要自行接入 JSPatch,统一接入 JSPatch 平台,让热修复在一个安全和可控的环境下使用。原因详见 这里

JSPatch bridges Objective-C and JavaScript using the Objective-C runtime. You can call any Objective-C class and method in JavaScript by just including a small engine. That makes the APP obtaining the power of script language: add modules or replacing Objective-C code to fix bugs dynamically.

JSPatch is still in development, welcome to improve the project together.

Notice: Please go to Wiki to get full document.

Example

@implementationAppDelegate - (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [JPEngine startEngine]; NSString *sourcePath = [[NSBundlemainBundle] pathForResource:@"demo"ofType:@"js"]; NSString *script = [NSStringstringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil]; [JPEngine evaluateScript:script]; self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; [self.window addSubview:[selfgenView]]; [self.window makeKeyAndVisible]; returnYES; } - (UIView *)genView { return [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 320)]; } @end
// demo.jsrequire('UIView, UIColor, UILabel')defineClass('AppDelegate',{// replace the -genView methodgenView: function(){varview=self.ORIGgenView();view.setBackgroundColor(UIColor.greenColor())varlabel=UILabel.alloc().initWithFrame(view.frame());label.setText("JSPatch");label.setTextAlignment(1);view.addSubview(label);returnview;}});

You can also try to use JSPatch Convertor to convertor code from Objective-C to JavaScript automatically.

Installation

CocoaPods

CocoaPods is a dependency manager for Objective-C, which automates and simplifies the process of using 3rd-party libraries like JSPatch in your projects. See the "Getting Started" guide for more information.

# Your Podfileplatform:ios,'6.0'pod'JSPatch'

Manually

Copy JSEngine.mJSEngine.hJSPatch.js in JSPatch/ to your project.

Usage

Objective-C

  1. #import "JPEngine.h"
  2. call [JPEngine startEngine]
  3. exec JavasScript by [JPEngine evaluateScript:@""]
[JPEngine startEngine]; // exec js directly [JPEngine evaluateScript:@"\ var alertView = require('UIAlertView').alloc().init();\ alertView.setTitle('Alert');\ alertView.setMessage('AlertView from js'); \ alertView.addButtonWithTitle('OK');\ alertView.show(); \"]; // exec js file from network [NSURLConnectionsendAsynchronousRequest:[NSURLRequestrequestWithURL:[NSURLURLWithString:@"http://cnbang.net/test.js"]] queue:[NSOperationQueuemainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { NSString *script = [[NSStringalloc] initWithData:data encoding:NSUTF8StringEncoding]; [JPEngine evaluateScript:script]; }]; // exec local js fileNSString *sourcePath = [[NSBundlemainBundle] pathForResource:@"sample"ofType:@"js"]; NSString *script = [NSStringstringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil]; [JPEngine evaluateScript:script];

JavaScript

Base Usage

//requirerequire('UIView, UIColor, UISlider, NSIndexPath')// Invoke class methodvarredColor=UIColor.redColor();// Invoke instance methodvarview=UIView.alloc().init();view.setNeedsLayout();// set proertyview.setBackgroundColor(redColor);// get property varbgColor=view.backgroundColor();// multi-params method (use underline to separate)// OC:NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:1];varindexPath=NSIndexPath.indexPathForRow_inSection(0,1);// method name contains underline (use double undeline to represent)// OC: [JPObject _privateMethod];JPObject.__privateMethod()// use .toJS() to convert NSArray / NSString / NSDictionary to JS type.vararr=require('NSMutableArray').alloc().init()arr.addObject("JS")jsArr=arr.toJS()console.log(jsArr.push("Patch").join(''))//output: JSPatch// use hashes to represent struct like CGRect / CGSize / CGPoint / NSRangevarview=UIView.alloc().initWithFrame({x:20,y:20,width:100,height:100});varx=view.bounds().x;// wrap function with `block()` when passing block from JS to OC// OC Method: + (void)request:(void(^)(NSString *content, BOOL success))callbackrequire('JPObject').request(block("NSString *, BOOL",function(ctn,succ){if(succ)log(ctn)}));// GCDdispatch_after(1.0,function(){// do something})dispatch_async_main(function(){// do something})

Go to wiki page for more details: Base Usage

defineClass

You can redefine an existing class and override methods.

// OC@implementationJPTableViewController ... - (void)tableView:(UITableView *)tableViewdidSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSString *content = self.dataSource[[indexPath row]]; //may cause out of bound JPViewController *ctrl = [[JPViewController alloc] initWithContent:content]; [self.navigationController pushViewController:ctrl]; } - (NSArray *)dataSource { return @[@"JSPatch", @"is"]; } - (void)customMethod { NSLog(@"callCustom method") } @end
// JSdefineClass("JPTableViewController", { // instance method definitions tableView_didSelectRowAtIndexPath: function(tableView, indexPath) { var row = indexPath.row() if (self.dataSource().count() > row) { //fix the out of bound bug here var content = self.dataSource().objectAtIndex(row); var ctrl = JPViewController.alloc().initWithContent(content); self.navigationController().pushViewController(ctrl); } }, dataSource: function() { // get the original method by adding prefix 'ORIG' var data = self.ORIGdataSource().toJS(); return data.push('Good!'); } }, {})

Go to wiki page for more details: Usage of defineClass

Extensions

There are some extensions provide support for custom struct type, C methods and other functional, call +addExtensions: after starting engine to add extensions:

@implementationAppDelegate - (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [JPEngine startEngine]; //add extensions after startEngine [JPEngine addExtensions:@[@"JPInclude", @"JPCGTransform"]]; NSString *sourcePath = [[NSBundlemainBundle] pathForResource:@"demo"ofType:@"js"]; NSString *script = [NSStringstringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil]; [JPEngine evaluateScript:script]; } @end
include('test.js')//include function provide by JPInclude.mvarview=require('UIView').alloc().init()//CGAffineTransform is supported in JPCGTransform.mview.setTransform({a:1,b:0,c:0,d:1,tx:0,ty:100})

Extensions can be added dynamiclly in JS, which is recommended:

require('JPEngine').addExtensions(['JPInclude','JPCGTransform'])// `include()` and `CGAffineTransform` is avaliable now.

You can create your own extension to support custom struct type and C methods in project, see the wiki page for more details: Adding new extensions

Enviroment

  • iOS 7+, forward compatibility with iOS 6
  • JavaScriptCore.framework
  • Support armv7/armv7s/arm64

About

JSPatch bridge Objective-C and Javascript using the Objective-C runtime. You can call any Objective-C class and method in JavaScript by just including a small engine. JSPatch is generally used to hotfix iOS App.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published
close