-
Notifications
You must be signed in to change notification settings - Fork 2.2k
defineProtocol 使用文档
##问题
JSPatch 为一个类新增原本 OC 不存在的方法时,所有的参数类型都会定义为 id
类型,因为这种在 JS 里新增的方法一般不会在 OC 上调用,而是在 JS 上用,JS 可以认为一切变量都是对象,没有类型之分,所以全部定义为 id
类型。
但有种场景,需要让新增的方法参数类型不是 id
,那就是,在 OC 里 .h
文件定义了一个方法,这个方法里的参数和返回值不都是 id
类型,但是在 .m
文件中由于疏忽没有实现这个方法,导致其他地方调用这个方法时找不到这个方法造成 crash,要用 JSPatch 修复这样的 bug,就需要 JSPatch 可以动态添加指定参数类型的方法。对此可以用 defineProtocol()
接口定义参数类型,再在 defineClass()
中实现,就可以动态添加指定参数类型的方法了。
##API
defineProtocol(protocolDeclaration, instanceMethods , classMethods)
@param protocolDeclaration
:字符串,新增protocol的名字
@param instanceMethods
:字典,要添加到protocol的实例方法
@param classMethods
:字典,要添加到protocol的类方法
需要说明的是,在runtime中,协议一旦注册后就不可再修改,所以只能新增协议
- 在defineProtocol中
protocolDeclaration
参数输入协议名称 - 在defineProtocol中
instanceMethods
参数输入协议内实例方法的字典,以方法名为Key,Value也是一个字典,是实例方法的信息 - 在defineProtocol中
classMethods
参数输入协议内类方法的字典,以方法名为Key,Value也是一个字典,是类方法的信息
##定义Protocol中的实例方法
1.key为方法名,字符串,命名方式和JsPatch的defineClass一致
2.Value是个字典,包含3个key,paramsType``returnType
为必备参数,typeEncode
为可选参数,都是字符串。
- paramsType:顺序输入参数类型,用“,”逗号来分隔
- returnType:输入返回值类型
- typeEncode:可选,对于不支持的类型,可以通过这个字段手动填写
3.在OC中定义的协议实例方法
@protocol JPProtocol <NSObject>
-(int)testProtocol:(BOOL)oye;
-(NSString*)testProtocol:(CGRect)rect withB:(float)f withC:(NSArray*)arr;
@end
4.在Js中定义协议实例方法
defineProtocol('JPProtocol',{
testProtocol:{
paramsType:"BOOL",
returnType:"int",
},
testProtocol_withB_withC:{
paramsType:"CGRect,float,NSArray",
returnType:"id",
},
}
##定义Protocol中的类方法
defineProtocol() 第三个参数就是要添加或覆盖的类方法,规则与上述实例方法一致。
//OC
@protocol JPProtocol <NSObject>
+(int)testProtocol:(BOOL)oye;
@end
//JS
defineProtocol('JPTestProtocol',{
//实例方法
},{
//类方法
testProtocol:{
paramsType:"BOOL",
returnType:"int",
},
})
##参数类型
1.paramsType
和 returnType
中可以直接使用的参数类型位包括id
,BOOL
,int
,void
,char
,short
,unsigned short
,unsigned int
,long
,unsigned long
,long long
,float
,double
,CGFloat
,CGSize
,CGRect
,CGPoint
,CGSize
,CGVector
,UIEdgeInset
,NSInteger
,SEL
,block
2.参数是 OC 对象 NSObject
,比如NSArray
,CustomObject
,可以写作id
,也可以直接写类名,效果一样
paramsType:"id" paramsType:"CustomObject"
3.对于无法支持的参数,比如其他结构体,customStruct
,可以使用typeEncode
可选字段
testProtocolConstumStruct:{
paramsType:"unknown",
returnType:"int",
typeEncode:"i@:{CGVector=dd}"
},
4.当使用 typeEncode
时,类型字符串可以不必匹配任意填写,比如填写unknown,比如填写xxx,但是要求paramsType
的个数必须保证准确
5.自行填写的 typeEncode
,可以通过在项目中使用OC代码,在运行时通过系统获取
SEL selstr = NSSelectorFromString(@"testProtocolConstumStruct:");
Method method = class_getInstanceMethod(class, selstr);
const char* type = method_getTypeEncoding(logmanagermethod);
##更多使用Case参见newProtocolTest.js
##使用defineProtocol为defineClass新增含有非id类型的方法
defineClass新增不存在的方法的时候要求参数均为id类型,当使用defineProtocol新增含有任意类型参数方法的协议的时候,defineClass遵守新增协议,即可添加任意类型参数方法
defineClass('ViewController:UIViewController <lalalala>', {
testProtocolConstumStruct:function(oye){
return 6;
},
}