网页交互框架/()
1初始化 注册moduleAPIs dict
1代码 FDWebViewController初始化时,要顺便把WAUserInterfaceAPI ,WebAppBridge 初始化
- (void)viewDidLoad
{
self.webView = [[WAWebView alloc] init];
self.webView.moduleAPIs = @[[WADeviceAPI sharedInstance],
[[WAUserInterfaceAPI alloc] initWithContext:self],
[WAUserAPI sharedInstance]];
}
//self.webView.moduleAPIs _ type is NSMutableArray,val is:
[0] (null) @"user" : (no summary)
[1] (null) @"device" : (no summary)
[2] (null) @"UI" : (no summary) (看情况手工处理)
2其中内部调用
//self.webView.moduleAPIs 中 setmoduleAPIs 方法
//调用某类里面的func. 其中obj为对应类,module为该类对应方法,该方法返回对应Key
NSString *module = (NSString *)[((NSObject *)obj) performSelector:@selector(module)];
[self.webAppBridge registerAPI:obj forModule:module]
//对应其他类的
- (NSString *)module
{
return @"user";
}
2点击WEB 截取Url
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
NSURL *url = request.URL;
NSString *module = url.host;
NSString *json = url[@"p"];
NSString *callback = url[@"cb"];
NSArray *pathComponents = url.pathComponents;
NSString *name = [pathComponents objectAtIndex:1];
NSData *jsonData = [json dataUsingEncoding:NSUTF8StringEncoding];
id jsonObject =[NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingAllowFragments
error:&parseError];
}
url NSURL * @"webapi://UI/goto?p=%7B%22uri%22%3A%22djcar%3A%2F%2FPostDetailPage%3Fint%3D1%26long%3D14574327428951033%22%7D" 0x00007f9618e90820 0x00007ffed1cf1290
- 如上链接 转换后如下,并传入_invokeClientMethod
module = 'UI'
name = 'goto'
parameter = jsonObject (%7B%22uri%22%3A%22djcar%3A%2F%2FPostDetailPage%3Fint%3D1%26long%3D14574327428951033%22%7D)
callbackBlock = nil
3分析Url中host作为Key找回对应moduleAPIs 所对应的类 调整对应方法
- (id)_invokeClientMethod:(NSString *)module
name:(NSString *)name
parameter:(id)parameter
callback:(WACallback)callback
{
id<WebAppAPI> api = [self _apiForModule:module];
id result = [api invokeClientMethod:name parameter:parameter callback:callback];
return result;
}
- (id<WebAppAPI>)_apiForModule:(NSString *)module
{
//conformsToProtocol:@protocol()是用来检查对象是否实现了指定
id obj = [self.moduleAPIs objectForKey:module];
return [obj conformsToProtocol:@protocol(WebAppAPI)] ? obj : nil;
}
4协议存在情况下 跳转对应func
- (id)invokeClientMethod:(NSString *)name parameter:(id)parameter callback:(WACallback)callback
{
// [+] WABaseAPIReflectionImpl invokeClientMethod
if (callback == nil) {
[Logger debug:NSStringFromClass(self.class) message:@"void(%@, %@, %@)", self.module, name, parameter];
}else{
[Logger debug:NSStringFromClass(self.class) message:@"void(%@, %@, %@, %@)", self.module, name, parameter, callback];
}
NSString *selectorName = [NSString stringWithFormat:@"%@:callback:", name];
PKLog(@"调用方法是 %@:",name);
SEL selector = NSSelectorFromString(selectorName);
if (![self respondsToSelector:selector])
{
return nil;
}
// Call the selector
id result = nil;
//methodForSelector:方法,让我们可以获取到方法的指针
IMP imp = [self methodForSelector:selector];
if (imp) {
//强制转换函数指针
id(*func)(id, SEL, id, WACallback) = (void *)imp;
result = func(self, selector, parameter, callback);
}
return result;
}
//result = func(self, selector, parameter, callback);
selector SEL "goto:callback:" 0x00000001037a6a3e
parameter __NSCFDictionary * 1 key/value pair 0x00007f8a00c92400
callback WACallback 0x0 0x0000000000000000
5具体实现func
- (id)goto:(id)parameter callback:(WACallback)callback
{
NSString *uri = parameter[@"uri"];
PKLog(@"跳转的URL是 %@",uri);
[[URINavigationCenter sharedObject] handleURI:uri fromViewController:(UIViewController *)self.context animated:YES];
return nil;
}
uri __NSCFString * @"djcar://PostDetailPage?int=1&long=14574327428951033" 0x00007fe864910140
PS所有网页加载前要先注入以下代码
JS源代码 WAWebAPI.js
oc 注入
- (void)_injectBridgeJavascript:(UIWebView *)webView
{
NSString *filePath = [[NSBundle mainBundle]
pathForResource:@"WAWebAPI"
ofType:@"js"];
NSString *js = [NSString stringWithContentsOfFile:filePath
encoding:NSUTF8StringEncoding error:nil];
[webView stringByEvaluatingJavaScriptFromString:js];
}
js 代码
invokeClientMethod: function(module, name, parameters, callback) {
var url = 'webapi://' + module + '/' + name + '?p=' + encodeURIComponent(JSON.stringify(parameters || {}));
if (callback) {
var name;
if (typeof callback == "function") {
name = WebApiCore.createGlobalFuncForCallback(callback);
} else {
name = callback;
}
url = url + '&cb=' + name;
}
js data
<div class="set-collect-topic-list" onclick="
WebApiCore.invokeClientMethod('Info','statEvent', {'types':['string','JSONObject'],'args':['index_toutiaobrowse',{'tiezi-id':'14538013744691619'}]});
WebApiCore.invokeClientMethod('UI', 'goto', {'uri' :'djcar://PostDetailPage?int=1&long=14538013744691619'});
">