整个代码包括
因为是基于中间人模式,所以VKMediatorAction是整个代码的核心。VKMediatorAction的主代码并未实现什么核心内容,只是写了一个单例以备将来可能的功能扩展。从现有的代码角度来看,可以删除单例,全部写成类方法。
本地调用
VKMediatorAction的category是中间人的主要代码所在,使用category的方式可以在业务无限庞大的时候分拆代码便于管理。可以在demo工程中的VKMediatorAction+webVC.m
的源码中查看
-(void)doAlertWebViewControllerWith:(NSString *)title withMainUrl:(NSString *)url
{
Class cls = NSClassFromString(@"WebViewController");
id vc = [[cls alloc]VKCallSelectorName:@"initWithTitle:url:" error:nil,title,url];
[vc VKCallSelectorName:@"doAlertAction" error:nil];
}
-(id)getWebViewControllerWithTitle:(NSString *)title withMainUrl:(NSString *)url
{
Class cls = NSClassFromString(@"WebViewController");
id vc = [[cls alloc]VKCallSelectorName:@"initWithTitle:url:" error:nil,title,url];
return vc;
}
可以看到所有的API设计都是native api,你可以设计任意的参数命名,任意的参数种类。
换句话说,如果想执行本地调用,只需要引入VKMediatorAction,然后调用你想要的api即可
- (IBAction)native1click:(id)sender {
[[VKMediatorAction sharedInstance] doAlertWebViewControllerWith:@"webview" withMainUrl:@"http://awhisper.github.io"];
}
- (IBAction)native2click:(id)sender {
UIViewController *vc = [[VKMediatorAction sharedInstance]getWebViewControllerWithTitle:@"webview" withMainUrl:@"http://awhisper.github.io"];
[self.navigationController pushViewController:vc animated:YES];
}
需要注意的是,VKMediatorAction+webVC.m
内的源码完全不import业务模块,因此需要使用runtime的方式去调用对应方法,而我的源码里有一个封装的VKMsgSend的工具,使用这个工具可以减少写runtime代码的成本。这个方法就是工具提供的,后续还会详细介绍。
远程调用
当你需要使用url的方式打开界面的时候,首先,你需要让中间人能够处理url传来的字典型参数,因此特意为上面的2个mediatoraction增加了处理字典参数的版本。可以看到,这个代码最初符合设计初衷,url的action最后还是会调用原来的native的action。
-(void)doAlertWebViewControllerWithURLParams:(NSDictionary *)params
{
NSString *title = params[@"title"];
NSString *url = params[@"url"];
[self doAlertWebViewControllerWith:title withMainUrl:url];
}
-(id)getWebViewControllerWithURLParams:(NSDictionary *)params
{
NSString *title = params[@"title"];
NSString *url = params[@"url"];
return [self getWebViewControllerWithTitle:title withMainUrl:url];
}
完成了Mediator对URL参数的支持,其实就已经可以直接使用VKURLAction了。
VKURLAction使用
在使用VKURLAction时,需要提前指定url的scheme和host,一旦指定了app的scheme和host,所有不匹配scheme与host的url都不会被识别。具体可以参考demo源码,源码很简单,这里不再赘述。
VKURLAction支持对URL加入sign校验,如果url开启了sign校验功能,所有url必须附带sign参数,并且符合签名校验规则,否则不会进行识别跳转。具体代码可看源码,这些都是细节,这里不再细说。
只要完成了Mediator对URL参数的支持,其实就已经可以直接使用VKURLAction。比如我们已经写好了getWebViewControllerWithURLParams:
方法,那么我们可以直接把getWebViewControllerWithURLParams
当做url的path,以scheme://host/path?params=aa&parms2=bb
的形式来打开url,这样就会自动把url中的参数解析成字典,传入到Mediator的对应方法里。
//初始化URLAction
[VKURLAction setupScheme:@"demo" andHost:@"nativeOpenUrl"];
//写url
NSString * url =@"demo://nativeOpenUrl/getWebViewControllerWithURLParams?title=webView&url=http%3A%2F%2Fawhisper.github.io";
//openURL
[VKURLAction doActionWithUrlString:url];
更多使用方法请参考demo工程。
URL生成
如果对如何编写url不熟悉,VKURLAction提供了接口来自动生成接口,尤其是在开启了签名校验后,url的签名规则会比较复杂。如果想测试的话,可以使用相关接口自动生成url,避免手动编写出错。
url的参数必须经过url标准的encode,这一点,自动生成url工具已经实现,如果由其他方式生成url(如server下发等),请注意调试。
URL简写
把getWebViewControllerWithURLParams当做一个path名字拼接到url里面实在有点冗长,也不太好记,因此VKURLAction提供了方法来注册简写(注意这不是必须的,不写也能执行url)
//注册简写
[VKURLAction mapKeyword:@"openWeb" toActionName:@"getWebViewControllerWithURLParams"];
//url就可以这么写了
NSString * url =@"demo://nativeOpenUrl/openWeb?title=webView&url=http%3A%2F%2Fawhisper.github.io";
注册了简写之后,写url也清爽了不少,也减少了别人猜测我们app代码的问题。╮(╯_╰)╭
URLParser
整个VKURLAction都是依托在URLParser这个模块之上,它可以解析url,识别出url中的scheme,host,path和每个参数,拼接到字典中,验证签名的可靠性。具体代码见源码,这部分代码不是很复杂。