WebViewJavaScriptBridgeの登録方法を優雅に使用
4042 ワード
最近WebViewJavaScriptBridgeを研究して、ネット上の原理は大体同じで、自分と結びつけてソースコードを見て、流れがはっきりして、まとめてみます.1 WebViewJavaScriptBridgeはWKWebViewが使用するかURLをブロックするかの方法に合わせてJSとWebViewのインタラクションを実現する.簡単に使うと、まずページのロードが終わった後、JSをページに注入し、JSメソッド呼び出し時にパラメータなどを変換してwebviewが認識をブロックできるようにします.内部では、辞書のようなメカニズムを使用して、登録されたメソッド名と対応する処理を格納します.2公的文書の登録方法の例
このような状況は簡単でいいですが、方法が多い場合は、頭が痛いです.私のソリューションは、JSの呼び出しを専門に処理するクラスを作成することです.クラス中のメソッドの名前はJS呼び出しと同じで、runtimeでメソッドのリストを取得し、self.jsBridge登録方法.配布によってメソッドを呼び出す.最後の姿はこうだった
具体的な解決策は、まずメソッドのリストを取得し、変換後のJSNameと、関係のないメソッドをフィルタリングすることを覚えています.
辞書を半分取った.JSNameでSELを変換してから転送します.
そしてperformSelectorで転送します.
webビューではこれで終わりです
1つのcontrollerに登録方法の実装を書く必要はありません.
[self.jsBridge registerHandler:jsName
handler:^(id data, WVJBResponseCallback responseCallback) {
//
}];
このような状況は簡単でいいですが、方法が多い場合は、頭が痛いです.私のソリューションは、JSの呼び出しを専門に処理するクラスを作成することです.クラス中のメソッドの名前はJS呼び出しと同じで、runtimeでメソッドのリストを取得し、self.jsBridge登録方法.配布によってメソッドを呼び出す.最後の姿はこうだった
// JS
for (NSString *jsName in [self.helper.ymHelperMethodDic allKeys]) {
__weak typeof(self) weakSelf = self;
[self.jsBridge registerHandler:jsName
handler:^(id data, WVJBResponseCallback responseCallback) {
__strong typeof(weakSelf) strongSelf = weakSelf;
[strongSelf.helper ymHelperHandleName:jsName
data:data
callBack:responseCallback];
}];
}
具体的な解決策は、まずメソッドのリストを取得し、変換後のJSNameと、関係のないメソッドをフィルタリングすることを覚えています.
/**
* runtime
*
* @return js
*/
- (NSDictionary *)ymHelperMethodListDic
{
unsigned int count;
Method *methods = class_copyMethodList([WebViewJSHandler class], &count);
NSMutableDictionary *methodDictionary = [NSMutableDictionary dictionaryWithCapacity:count];
for (int i = 0; i < count; i++)
{
Method method = methods[i];
SEL selector = method_getName(method);
NSString *name = NSStringFromSelector(selector);
/**
*
*/
if (![name containsString:@"mHelper"] &&
![name containsString:@"."] &&
![name containsString:@"dealloc"]) {
NSString *jsName = [[name componentsSeparatedByString:@":"] firstObject];
NSLog(@" ==== %@",name);
NSLog(@"js ==== %@",jsName);
[methodDictionary setObject:name forKey:jsName];
}
}
return methodDictionary;
}
辞書を半分取った.JSNameでSELを変換してから転送します.
/**
* methodName
*
* @param methodName
* @param data
* @param responseCallback
*/
- (void)ymHelperHandleName:(NSString *)methodName
data:(id)data
callBack:(YMResponseCallback)responseCallback{
NSString *selString = [self ymHelperFindSELByJSName:methodName];
// string to SEL
SEL sel = NSSelectorFromString(selString);
if ([self.ymHelperWebViewJSHandler respondsToSelector:sel]) {
//
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[self.ymHelperWebViewJSHandler performSelector:sel withObject:data withObject:responseCallback];
#pragma clang diagnostic pop
}
}
そしてperformSelectorで転送します.
webビューではこれで終わりです
// JS
for (NSString *jsName in [self.helper.ymHelperMethodDic allKeys]) {
__weak typeof(self) weakSelf = self;
[self.jsBridge registerHandler:jsName
handler:^(id data, WVJBResponseCallback responseCallback) {
__strong typeof(weakSelf) strongSelf = weakSelf;
[strongSelf.helper ymHelperHandleName:jsName
data:data
callBack:responseCallback];
}];
}
1つのcontrollerに登録方法の実装を書く必要はありません.