原理
dsbridge的核心原理是在WebView中注入一个全局的JavaScript对象,并在这个对象中定义方法,这些方法会调用iOS原生代码的函数。同时,iOS原生代码也能在dsbridge中注册方法,供JavaScript调用。这种方式实现了Web与原生代码之间的互通。
Native调用h5
JavascriptCallHandlerManager
创建一个单例JavascriptCallHandlerManager,该单例提供一个注册方法,传入一个实现了JavaScriptCallHandlerManagerDelegate协议的对象。一般是自定义的webview,此传入的对象作为该类的私有变量。
统一提供所有的业务方法,比如点击了开始。
+(void)startSomething;
在内部封装统一调用实现
+ (void)startSomething {
[[JavascriptCallHandlerManager sharedInstance].call callHandler:@"startSomething" arguments:@[]];
}
对于外部,只需要在点击事件的时候调用即可。
[JavascriptCallHandlerManager startSomething]
JavaScriptCallHandlerManagerDelegate
此协议声明需要实现 callHandler
的相关方法。
@optional
- (void)callHandler:(NSString *)methodName arguments:(NSArray *)args;
- (void)callHandler:(NSString *)methodName completionHandler:(void (^)(id _Nullable value))completionHandler;
- (void)callHandler:(NSString *)methodName arguments:(NSArray *)args completionHandler:(void (^)(id _Nullable value))completionHandler;
XXDWKWeview
DWKWebview是DSbridge所创建的WKWebview的子类。而我们需要创建DWKWebview的子类XXDWKWeview。DWKWebview即实现了上面的JavaScriptCallHandlerManagerDelegate协议中的方法,将其传入作为JavascriptCallHandlerManager的属性。
在这里面,我们可以做一些在调用DWKWebview的call方法之前的拦截,以此来实现一些自定义功能,可以不用。
// 交换方法
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[XXWKWebView xx_methodSwizzlingWithClass:[XXWKWebView class] oriSEL:@selector(call::) swizzledSEL:@selector(exchangeCall::)];
});
}
// 自定义一些拦截事件
- (NSString *)call:(NSString *)method :(NSString *)argStr {
if ([@"setNavigationBadge" isEqualToString:method] || [@"callQSLive" isEqualToString:method] || [@"showNavigationBar" isEqualToString:method] || [@"hideNavigationBar" isEqualToString:method]) {
NSString *selfAddress = [NSString stringWithFormat:@"%p", (__bridge void *)(self)];
NSDictionary *args = [JSBUtil jsonStringToObject:argStr];
if ([args isKindOfClass:[NSDictionary class]]) {
NSMutableDictionary *mArgs = [NSMutableDictionary dictionaryWithDictionary:args];
NSDictionary *data = mArgs[@"data"];
if (data) {
if ([data isKindOfClass:[NSDictionary class]]) {
NSMutableDictionary *mData = [NSMutableDictionary dictionaryWithDictionary:data];
mData[@"webView"] = selfAddress;
mArgs[@"data"] = mData;
} else if ([data isKindOfClass:[NSString class]]) {
NSMutableDictionary *mData = [NSMutableDictionary dictionary];
mData[@"webView"] = selfAddress;
mData[@"data"] = data;
mArgs[@"data"] = mData;
}
}
argStr = [JSBUtil objToJsonString:mArgs];
}
}
return [super call:method :argStr];
}
h5调native
JavaScriptBaseHandler
创建JavaScriptBaseHandler,其遵循JSHandlerProtocol协议。在JavaScriptBaseHandler中实现所有的协议中的方法,再在方法中调用navtive的具体实现方法。
可以使用具体的业务模块创建例如VideoJavaScriptBaseHandler,作为JavaScriptBaseHandler的属性,然后调用VideoJavaScriptBaseHandler的具体方法。
也可以使用多代理模式,统一找到所有在该类中注册了此方法的对象,执行响应的方法。
JSHandlerProtocol
与JS约定的所有方法。
XXDWKWebiew
DWKWebiew提供了注册方法,如下:
/**
* Add a Javascript Object to dsBridge with namespace.
* @param object
* which implemented the javascript interfaces
* @param namespace
* if empty, the object have no namespace.
**/
- (void)addJavascriptObject:(id _Nullable ) object namespace:(NSString * _Nullable) namespace;
创建XXDWKWebiew,继承DWKWebiew,在初始化的时候调用来注册。
JavaScriptBaseHandler *baseHandler = [[JavaScriptBaseHandler alloc] init];
[xxWebView addJavascriptObject:baseHandler namespace:nil];