JSPatch 学习

引言

好久前就已经了解到JSPatch(JSPatch是iOS平台的热修复框架,能够及时的修复线上的一些小bug,iOS应用审核时间之长,大家都懂得),一直以来都没有抽出时间去学习,今天抽出时间来学习下,突然又发现只有官方的一些教程,自己照着写写满满都是泪(崩溃的次数多)。学JSPatch写法,首先大家需要先补一下JavaScript的知识。

基础用法

关于基础的用法大家可以先看官方的Wiki,大致有13个知识点,我这里直接就上用法了。

require

首先,用到哪个类就需要require一下,否则会崩溃,比如UIView、UILabel等等,中间逗号隔开

1
require('UILabel,UIView');

调用OC的方法

因为JavaScript是链式语法,所以说和写OC有很大的不同,写的时候要注意

1
2
3
require('UIView, UIColor');
var view = UIView.alloc().init();//实例方法
var red = UIColor.redColor();//类方法

UIView 有很多的Property,这些Property如何调用呢?

等于调用这个 Property 的 getter / setter 方法,获取时记得加 (),如:

1
2
3
require('UIView, UIColor');
var view = UIView.alloc().init();
view.setBackgroundColor(UIColor.grayColor());

常量、枚举、宏、全局变量

Objective-C 里的常量/枚举不能直接在 JS 上使用,可以直接在 JS 上用具体值代替:

1
2
var label = UILabel.alloc().init();
label.setTextAlignment(1);//这里需要写具体的值

宏也不使用,若定义的宏是一个值,可以在 JS 定义同样的全局变量代替,若定义的宏是程序,可以在JS展开宏

1
2
3
4
5
#define TABBAR_HEIGHT 40
#define SCREEN_WIDTH [[UIScreen mainScreen] bounds].size.height
[view setWidth:SCREEN_WIDTH height:TABBAR_HEIGHT];
//JS
view.setWidth_height(40, UIScreen.mainScreen().bounds().height);

若宏的值是某些在底层才能获取到的值,例如 CGFLOAT_MIN,可以通过在某个类或实例方法里将它返回,或者用添加扩展的方式提供支持,

1
2
3
4
5
6
7
8
@implementation JPMacroSupport
+ (void)main:(JSContext *)context
{
context[@"CGFLOAT_MIN"] = ^CGFloat() {
return CGFLOAT_MIN;
}
}
@end
1
2
require('JPEngine').addExtensions(['JPMacroSupport'])
var floatMin = CGFLOAT_MIN();

当然全局变量也是如此:

1
2
3
4
5
6
static NSString *name;
@implementation JPTestObject
+ (NSString *)name {
return name;
}
@end
1
var name = JPTestObject.name() //拿到全局变量值

defineClass

在 defineClass 里定义 OC 已存在的方法即可覆盖:

1
2
3
4
defineClass('ViewController', {
viewDidLoad: function() {
},
});

如果想调用原方法,在方法名前加 ORIG 即可调用未覆盖前的 OC 原方法:

1
2
3
4
5
defineClass('ViewController', {
viewDidLoad: function() {
self.ORIGviewDidLoad();
},
});

下面是一个UILabel添加到View上的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
require('UILabel,UIView,UIColor,UIFont');
defineClass('ViewController', {
viewDidLoad: function() {
self.ORIGviewDidLoad();
var view = self.view();
var label = UILabel.alloc().initWithFrame({x:100, y:200, width:100, height:100});
label.setFont(UIFont.systemFontOfSize(10));
label.setTextAlignment(1);
label.setText("你好 !");
label.setBackgroundColor(UIColor.grayColor());
view.addSubview(label);
var background = UIView.alloc().initWithFrame({x:100,y:350,width:100,height:100});
background.setBackgroundColor(UIColor.grayColor());
self.setBackgroundView(background);
view.addSubview(self.backgroundView());
},
});

开始的时候一直不知道OC中的“self.view”在JavaScript中怎么调用,试了好久直接调用“self.view()”就行了。





参考:

官方的Wiki