您的位置:首页 > 其它

defineProtocol 使用文档

2016-03-03 11:50 555 查看


问题

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也是一个字典,是类方法的信息


示例

例如在 JPTestObject 对象中,
.h
头文件定义了这样一个接口:

@interface JPTestObject
- (NSString *)stringWithRect:(CGRect)rect withNum:(float)num withArray:(NSArray *)arr;
@end


但在 
.m
 文件中没有实现这个接口,导致其他地方调用这个方法时 crash。对此可以用 JSPatch 修复,分两个步骤:
把这个方法定义成一个 protocol
defineClass中实现这个 protocol

先看第一步,用 
defineProtocol
 接口把这个方法定义在一个新的 protocol 中:
defineProtocol('JPDemoProtocol',{
stringWithRect_withNum_withArray: {
paramsType:"CGRect, float, NSArray*",
returnType:"id",
},
}

接着第二步,在 defineClass 中实现这个方法:

defineClass('JPTestObject : NSObject <JPDemoProtocol>', {
stringWithRect_withNum_withArray:function(rect, num, arr){
//use rect/num/arr params here
return @"success";
},
}


大功告成,新增的方法参数类型会遵循 defineProtocol 里定义的类型,这时 OC 中再调用这个方法时就会调到在 JSPatch 新增的方法,让 APP 避免 crash。

更多使用 Case 参见 demo 工程里的 
newProtocolTest.js


更多参数类型

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);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: