Giter Site home page Giter Site logo

jeekwong / jspatch Goto Github PK

View Code? Open in Web Editor NEW

This project forked from bang590/jspatch

0.0 0.0 0.0 7.71 MB

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: MIT License

Objective-C 47.07% C 46.36% Ruby 0.54% JavaScript 1.84% C++ 3.85% PHP 0.34%

jspatch's Introduction

JSPatch

Travis CocoaPods Version License

中文介绍 | 文档 | 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

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{
    [JPEngine startEngine];
    NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"demo" ofType:@"js"];
    NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil];
    [JPEngine evaluateScript:script];
    
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    [self.window addSubview:[self genView]];
    [self.window makeKeyAndVisible];
    
    return YES;
}

- (UIView *)genView
{
    return [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 320)];
}

@end
// demo.js
require('UIView, UIColor, UILabel')
defineClass('AppDelegate', {
  // replace the -genView method
  genView: function() {
    var view = self.ORIGgenView();
    view.setBackgroundColor(UIColor.greenColor())
    var label = UILabel.alloc().initWithFrame(view.frame());
    label.setText("JSPatch");
    label.setTextAlignment(1);
    view.addSubview(label);
    return view;
  }
});

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 Podfile
platform :ios, '6.0'
pod 'JSPatch'

Manually

Copy JSEngine.m JSEngine.h JSPatch.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
[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];
}];

// exec local js file
NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"sample" ofType:@"js"];
NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil];
[JPEngine evaluateScript:script];

JavaScript

Base Usage

//require
require('UIView, UIColor, UISlider, NSIndexPath')

// Invoke class method
var redColor = UIColor.redColor();

// Invoke instance method
var view = UIView.alloc().init();
view.setNeedsLayout();

// set proerty
view.setBackgroundColor(redColor);

// get property 
var bgColor = view.backgroundColor();

// multi-params method (use underline to separate)
// OC:NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:1];
var indexPath = 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.
var arr = 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 / NSRange
var view = UIView.alloc().initWithFrame({x:20, y:20, width:100, height:100});
var x = view.bounds().x;

// wrap function with `block()` when passing block from JS to OC
// OC Method: + (void)request:(void(^)(NSString *content, BOOL success))callback
require('JPObject').request(block("NSString *, BOOL", function(ctn, succ) {
  if (succ) log(ctn)
}));

// GCD
dispatch_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
@implementation JPTableViewController
...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(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
// JS
defineClass("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:

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{
    [JPEngine startEngine];

    //add extensions after startEngine
    [JPEngine addExtensions:@[@"JPInclude", @"JPCGTransform"]];

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

@end
include('test.js')   //include function provide by JPInclude.m
var view = require('UIView').alloc().init()

//CGAffineTransform is supported in JPCGTransform.m
view.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

jspatch's People

Contributors

bang590 avatar albert438 avatar ipinka avatar rob2468 avatar lexrus avatar awhisper avatar li6185377 avatar tuoxie007 avatar sergiou87 avatar pc1849 avatar yauzz avatar whihail avatar leafduo avatar wenchaod avatar tigerzhang08 avatar fanliangbin320 avatar eniton avatar blankdlh avatar yirenjun avatar wutoz avatar mrsummer avatar lancy avatar jefferyfan avatar chieryw avatar fighting300 avatar decemberli avatar daixunry avatar lihuichaoo avatar victorteokw avatar xummer avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.