本文参考JSPatch wiki :https://github.com/bang590/JSPatch/wiki

1.概念

JSPatch是一个轻量的JS引擎,能够使用JavaScript语言来调用任何object-c接口,替换任何原生的方法。目前主要用于发步JS脚本替换原生Objective-C代码,实时修复线上bug

2.原理

利用OC语言的动态性,动态的修改类的方法和属性。在app启动的时候加载我们写好的JavaScript文件并通过JavaScriptCore来执行,用JS写好的类函数去篡改原有的OC函数。JSPatch只提供了篡改这个过程的代码,像部署线上Js代码、下载这些逻辑都得自己写。当然你可以用JSpatchSDK这个平台,这个平台帮我们部署JS代码、下载等一些逻辑。JSPatchSDK是收费的,也有免费版的。

3.部署

通过pod或者其他方式引入JSPatch,在didFinishLaunchingWithOptions函数加上如下代码:

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

部署完OC代码,我们就可以在index.js专心写JavaScript来修复线上的bug.

4.写JS代码

  • defineClass 用来定义(覆盖)一个类
  • defineClass(classDeclaration, [properties,] instanceMethods, classMethods)
    
    classDeclaration:字符串类型,代表类名字
    properties:一个字符串数组,代表要添加的属性列表
    instanceMethods:实例方法
    classMethods:累方法
  • 下面是一个例子:
  • 包含了22个知识点,学会了这22个点,就能完成JSPatch的大部分工作了
  • 如果还有不明白的地方可以看官网
  • 1.appDelegate.m文件
  •     [JPEngine startEngine];
    NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"js"];
    NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil];
    [JPEngine evaluateScript:script]; self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen] bounds]]; UINavigationController * navi = [[UINavigationController alloc]initWithRootViewController:[[MainViewController alloc]initWithNibName:@"MainViewController" bundle:nil]];
    self.window.rootViewController = navi;
    [self.window makeKeyAndVisible];
  • 2.MainViewController.h
  • //
    // MainViewController.h
    // JSPatchDemo
    //
    // Created by 朱国清 on 16/12/23.
    // Copyright © 2016年 bang. All rights reserved.
    // #import <UIKit/UIKit.h> @interface MainViewController : UIViewController @property (nonatomic,strong) NSArray * testArray;
    @property (nonatomic,strong) NSDictionary * testDictionary; @end
  • 3.MainViewController.m
  • //
    // MainViewController.m
    // JSPatchDemo
    //
    // Created by 朱国清 on 16/12/23.
    // Copyright © 2016年 bang. All rights reserved.
    // #import "MainViewController.h" @interface MainViewController () @property NSString * privateKey; @end @implementation MainViewController - (void)viewDidLoad {
    [super viewDidLoad]; self.testArray = @[@"Apple",@"Boy",@"Cat",@"Dog",];
    self.testDictionary = @{@"name":@"jack",@"age":@};
    self.privateKey = @"i am a private key"; [self initUI]; }
    // js 覆盖
    -(void)initUI{ if (false) {
    UIButton * btn = [[UIButton alloc]initWithFrame:CGRectMake(,, , )];
    [btn setTitle:@"go" forState:UIControlStateNormal];
    [btn setBackgroundColor:[UIColor brownColor]];
    [btn addTarget:self action:@selector(handleButton) forControlEvents:UIControlEventTouchUpInside]; }
    } -(void)handleButton{ } -(void)testString:(NSString *)string{
    NSLog(@"testString : %@",string);
    }
    - (void)testPointer:(NSError **)error {
    NSError *err = [[NSError alloc]initWithDomain:@"com.jspatch" code: userInfo:nil];
    *error = err;
    }
    -(void)request:(void(^)(NSString *content, BOOL success))callback
    {
    callback(@"I'm content", YES);
    }
    typedef void (^JSBlock)(NSString *str);
    -(JSBlock)getBlock{
    JSBlock block = ^(NSString *str) {
    NSLog(@"I'm %@",str);
    };
    return block;
    } - (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    } @end
  • 4.index.js
  • defineClass(
    'MainViewController',
    {
    viewWillAppear:function(animated){
    // 1.调用父类 self.super()
    self.super().viewWillAppear(animated);
    // 2.设置navigationBarHidden属性值 .setNavigationBarHidden(true)
    self.navigationController().setNavigationBarHidden(true);
    },
    initUI:function(){ // 3.oc的NSString对象,在JS里面是Object
    // 4.privateKey 为私有属性
    var privateKey = self.valueForKey("privateKey");
    self.testString(privateKey);
    console.log('privateKey:'+ privateKey); // 5.OC NSArray
    var item1 = self.testArray().objectAtIndex();
    console.log('item1:'+item1.toString());
    // 6.OC NSArray => JS array
    var jsArray = self.testArray().toJS();
    console.log('jsArray[0]:'+jsArray[]);
    // 7.OC NSDictionary
    var name1 = self.testDictionary().valueForKey('name');
    console.log('name1:'+name1);
    // 8.OC NSDictionary => JS json
    var dic = self.testDictionary().toJS();
    console.log('name2:'+dic['name']); // 10.获取属性 self.view()
    // 11.获取一个类 require('UIColor')
    self.view().setBackgroundColor(require('UIColor').grayColor());
    /*
    12.
    特殊变量
    point {x:, y: }
    size {width:, height:}
    CGRect {x:, y:, width:, height:}
    range {location:, length:}
    */
    var btn = require('UIButton').alloc().initWithFrame({x:, y:, width:, height:});
    btn.setBackgroundColor(UIColor.brownColor());
    // 13.多参数函数 [btn setTitle:forState:];以_代替: btn.setTitle_forState()
    btn.setTitle_forState('go',);
    // 14.Selector 用字符代替
    btn.addTarget_action_forControlEvents(self,'handlePress', << );
    self.view().addSubview(btn); // 15.block无法使用self,需要保存一下
    var slf = self;
    // 16.
    // 弱引用 var weakSelf = __weak(self)
    // 强引用 var strongSelf = __strong(self) // 17. block
    // block block的参数类型用字符串标示,block对象用NSBlock*类型
    /*
    从 JS 传 block 到 OC,有两个限制:
    A. block 参数个数最多支持6个。(若需要支持更多,可以修改源码)
    B. block 参数类型不能是 double / NSBlock / struct 类型。
    */
    self.request(block("NSString *, BOOL", function(ctn, succ) {
    if (succ)
    console.log(ctn) //output: I'm content slf.testString("block self"); }));
    // 18. oc 返回的block就是一个js函数,可以直接调用
    slf.getBlock()('JavaScrict'); // 19.GCD
    // JS
    dispatch_after(1.0, function(){
    console.log('dispatch_after 1s');
    })
    dispatch_async_main(function(){
    console.log('dispatch_async_main');
    })
    dispatch_sync_main(function(){
    console.log('dispatch_sync_main');
    })
    dispatch_async_global_queue(function(){
    console.log('dispatch_async_global_queue');
    }) // 20.参入id * 指针
    //malloc() pval() free() is provided by JPMemory extension
    require('JPEngine').addExtensions(['JPMemory'])
    var pError = malloc(sizeof("id"))
    self.testPointer(pError)
    var error = pval(pError)
    if (!error) {
    console.log("success")
    } else {
    console.log(error)
    }
    releaseTmpObj(pError)
    free(pError)
    },
    handlePress:function(){
    console.log('handlePress'); var vc = InfoViewController.alloc().init();
    self.navigationController().pushViewController_animated(vc,true);
    }
    }
    ) // 21.定义一个继承 UIViewController的类
    // 22.定义两个属性 url、info
    defineClass('InfoViewController : UIViewController',
    [
    'url',
    'info',
    ],
    {
    viewDidLoad:function(){
    self.super().viewDidLoad();
    self.navigationController().setNavigationBarHidden(false);
    self.view().setBackgroundColor(require('UIColor').whiteColor());
    self.setUrl('www.pingan.com.cn');
    console.log(self.url()); } }
    );


JSPatch学习笔记的更多相关文章

  1. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  2. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  3. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

  4. 2014年暑假c#学习笔记目录

    2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...

  5. JAVA GUI编程学习笔记目录

    2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...

  6. seaJs学习笔记2 – seaJs组建库的使用

    原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...

  7. CSS学习笔记

    CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...

  8. HTML学习笔记

    HTML学习笔记 2016年12月15日整理 Chapter1 URL(scheme://host.domain:port/path/filename) scheme: 定义因特网服务的类型,常见的为 ...

  9. DirectX Graphics Infrastructure(DXGI):最佳范例 学习笔记

    今天要学习的这篇文章写的算是比较早的了,大概在DX11时代就写好了,当时龙书11版看得很潦草,并没有注意这篇文章,现在看12,觉得是跳不过去的一篇文章,地址如下: https://msdn.micro ...

随机推荐

  1. 邓博泽 java最全的DateUtil工具类

    package com.kld.yijie.web.util; import org.slf4j.Logger;import org.slf4j.LoggerFactory; import java. ...

  2. swift基础:第六部分:类与对象

    http://reactnative.cn/docs/0.24/getting-started.html#content(react Native 开发文档) 互联网这个时代,你松懈一天,就会有很多很 ...

  3. iOS开发:http中的get和post请求

    什么是 HTTP ? 超文本传输协议(HTTP)的设计目的是保证客户端与服务器之间的通信. HTTP 的工作方式是客户端与服务器之间的请求-应答协议. web 浏览器可能是客户端,而计算机上的网络应用 ...

  4. 论文阅读(Chenyi Chen——【ACCV2016】R-CNN for Small Object Detection)

    Chenyi Chen--[ACCV2016]R-CNN for Small Object Detection 目录 作者和相关链接 方法概括 创新点和贡献 方法细节 实验结果 总结与收获点 参考文献 ...

  5. 夺命雷公狗----Git---7---GitHub当仓库本地使用(完)

    首先我们将github上的东西克隆到本地: 然后在本地创建一个文件夹,然后进入git命令行: 成功后如下所示: 将仓库里面的内容给克隆到本地了... 然后创建一个index.html然后添加进去: 在 ...

  6. 8139too.c网卡驱动简单分析

    从事linux C开发工作以来,工作内容主要是在应用层,对nginx和unbound等软件有些了解,也常对这2个软件进行二次开发. 对网络这块一直比较有兴趣.也很好奇网卡到底是怎么接受到报文的,以及报 ...

  7. 很久以前写的一个 ShareRestrictedSD 类

    代码中一开始的 几个 USES 单元,可能是多余的. unit ShareRestrictedSD; interface uses Windows, Messages, SysUtils, Class ...

  8. php常用函数time

    string date( string format [, int timestamp] )    参数 format 表示时间格式化的方式,可能的方式如下:    格式化方式     说明    Y ...

  9. python27 + windows7 报错 No module named requests

    1.下载插件包 地址: http://www.lfd.uci.edu/~gohlke/pythonlibs/#distribute 包名: requests-2.12.4-py2.py3-none-a ...

  10. 解析和风天气API的json(objective-C实现)

    暑假在家闲着没事干,心血来潮想做个天气预报APP玩玩,听说和风天气API很好,于是注册并试了下,结果它的JSON是这样的(拿我的家乡武义为例子) {"}},"status" ...