IOS主要有三种方式:WKWebView 、UIWebView、JavaScriptCoreWKWebView:
WKUserScript *script = [[WKUserScript alloc] initWithSource:@"window._dswk=true;"
injectionTime:WKUserScriptInjectionTimeAtDocumentStart
forMainFrameOnly:YES];
[configuration.userContentController addUserScript:script];
Native
类并添加相应的namespace
到javaScriptNamespaceInterfaces
。FDInternalApis
类注册了部分需要的方法,namespace
是_dsb
。FDInternalApis * interalApis= [[FDInternalApis alloc] init];
interalApis.webview=self;
[self addJavascriptObject:interalApis namespace:@"_dsb"];
if(object!=NULL){
[javaScriptNamespaceInterfaces setObject:object forKey:namespace];
NSLog(javaScriptNamespaceInterfaces.description);
}
[dwebview callHandler:@"addValue" arguments:@[@3,@4] completionHandler:^(NSNumber * value){
NSLog(@"%@",value);
}];
dsBridge.register('addValue', function (r, l) {
return r + l;
})
dsBridge.registerAsyn('append',function(arg1,arg2,arg3,responseCallback){
responseCallback(arg1+" "+arg2+" "+arg3);
})
NSString * json=[FDWebUtil objToJsonString:@{
@"method":info.method,@"callbackId":info.id,
@"data":[FDWebUtil objToJsonString: info.args]}];
[self evaluateJavaScript:[NSString stringWithFormat:@"window._handleMessageFromNative(%@)",json]
completionHandler:nil];
bridge.call("_dsb.returnValue", ret)
- (id) returnValue:(NSDictionary *) args{
void (^ completionHandler)(NSString * _Nullable)= handerMap[args[@"id"]];
if(completionHandler){
if(isDebug){
completionHandler(args[@"data"]);
}else{
@try{
completionHandler(args[@"data"]);
}@catch (NSException *e){
NSLog(@"%@",e);
}
}
if([args[@"complete"] boolValue]){
[handerMap removeObjectForKey:args[@"id"]];
}
}
return nil;
}
var str=dsBridge.call("testSyn","testSyn");
ret = prompt("_dsbridge=" + method, arg);
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable result))completionHandler;
NSString * prefix=@"_dsbridge=";
if ([prompt hasPrefix:prefix])
{
NSString *method= [prompt substringFromIndex:[prefix length]];
NSString *result=nil;
if(isDebug){
result =[self call:method :defaultText ];
}else{
@try {
result =[self call:method :defaultText ];
}@catch(NSException *exception){
NSLog(@"%@", exception);
}
}
completionHandler(result);
}
-(NSString *)call:(NSString*) method :(NSString*) argStr
{
NSArray *nameStr=[FDWebUtil parseNamespace:[method stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]];
id JavascriptInterfaceObject= [javaScriptNamespaceInterfaces valueForKey:nameStr[0]];
NSString *error=[NSString stringWithFormat:@"Error! \n Method %@ is not invoked, since there is not a implementation for it",method];
NSMutableDictionary*result =[NSMutableDictionary dictionaryWithDictionary:@{
@"code":@-1,@"data":@""}];
if(!JavascriptInterfaceObject){
NSLog(@"Js bridge called, but can't find a corresponded JavascriptObject , please check your code!");
}else{
method=nameStr[1];
NSString *methodOne = [FDWebUtil methodByNameArg:1 selName:method class:[JavascriptInterfaceObject class]];
NSString *methodTwo = [FDWebUtil methodByNameArg:2 selName:method class:[JavascriptInterfaceObject class]];
SEL sel=NSSelectorFromString(methodOne);
SEL selasyn=NSSelectorFromString(methodTwo);
NSDictionary * args=[FDWebUtil jsonStringToObject:argStr];
NSString *arg = [args safeObjectForKey:@"data"];
NSString * cb;
do{
if(args && (cb= args[@"_dscbstub"])){
if([JavascriptInterfaceObject respondsToSelector:selasyn]){
void (^completionHandler)(id,BOOL) = ^(id value,BOOL complete){
NSString *del=@"";
result[@"code"]=@0;
if(value!=nil){
result[@"data"]=value;
}
value=[FDWebUtil objToJsonString:result];
value=[value stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
if(complete){
del=[@"delete window." stringByAppendingString:cb];
}
NSString*js=[NSString stringWithFormat:@"try {%@(JSON.parse(decodeURIComponent(\"%@\")).data);%@; } catch(e){};",cb,(value == nil) ? @"" : value,del];
@synchronized(self)
{
UInt64 t=[[NSDate date] timeIntervalSince1970]*1000;
self->jsCache=[self->jsCache stringByAppendingString:js];
if(t-self->lastCallTime<50){
if(!self->isPending){
[self evalJavascript:50];
self->isPending=true;
}
}else{
[self evalJavascript:0];
}
}
};
SuppressPerformSelectorLeakWarning(
[JavascriptInterfaceObject performSelector:selasyn withObject:arg withObject:completionHandler];
);
break;
}
}else if([JavascriptInterfaceObject respondsToSelector:sel]){
id ret;
SuppressPerformSelectorLeakWarning(
ret=[JavascriptInterfaceObject performSelector:sel withObject:arg];
);
[result setValue:@0 forKey:@"code"];
if(ret!=nil){
[result setValue:ret forKey: