webview轉(zhuǎn)wkwebview遇到的坑
1?wkwebview里通過新窗品進行ajax的post請求時,cookie參數(shù)丟失
解決方案:不創(chuàng)建新wkwebview
2?原生網(wǎng)絡請求請求后cookie無法同步到wkwebview
@implementation WKWebView (cookieMgr)
- (void)syncCookies {
? ? NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
? ? if (@available(iOS 11.0, *)) {
? ? ? ? WKHTTPCookieStore *cookieStroe = self.configuration.websiteDataStore.httpCookieStore;
? ? ? ? if (cookies.count == 0) {
? ? ? ? ? ? return;
? ? ? ? }
? ? ? ? for (NSHTTPCookie *cookie in cookies) {
? ? ? ? ? ? [cookieStroe setCookie:cookie completionHandler:^{
? ? ? ? ? ? ? ? if ([[cookies lastObject] isEqual:cookie]) {
? ? ? ? ? ? ? ? ? ? return;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }];
? ? ? ? }
? ? }else {
? ? ? ? for (NSHTTPCookie *ck in cookies) {
? ? ? ? ? ? NSString *script = [NSString stringWithFormat:@"document.cookie='%@=%@;domain=%@;path=%@; expiresDate=\"%@\";isSecure=%@;sessionOnly=%@'",ck.name,ck.value,ck.domain,(ck.path?:@"/"),ck.expiresDate,(ck.isSecure ? @"TRUE":@"FALSE"),(ck.sessionOnly?@"TRUE":@"FALSE")];
? ? ? ? ? ? [self evaluateJavaScript:script completionHandler:nil];
? ? ? ? }
? ? }
}
@end
3?退出登錄時,再次登錄,部分頁面cookie錯誤
在退出登錄時,如果將WKProcessPool單例對象重置,會造成以前打開頁面和新打開cookie錯誤現(xiàn)象
4?關于原生方法調(diào)用的問題
webview采用jsexport為原生導出相應方法
wk通過js注入,創(chuàng)建原生對應對象并調(diào)用
JS代碼示例:
window.uz$q = {
? ? c:[],
? ? flag:true,
};
window.uz$cb = {
? ? fn:{},
? ? id:1,
? ? on:function(cbId, ret, err, del) {
? ? ? ? if (this.fn[cbId]) {
? ? ? ? ? ? this.fn[cbId](ret, err);
? ? ? ? ? ? if (del) {
? ? ? ? ? ? ? ? delete this.fn[cbId];
? ? ? ? ? ? }
? ? ? ? }
? ? }
};
function _onResultCallback(cbId, ret, err, del) {
? ? return function(){
? ? ? ? uz$cb.on(cbId, ret, err, del);
? ? }
}
function onResultCallback(cbId, ret, err, del) {
? ? setTimeout(_onResultCallback(cbId, ret, err, del), 0);
};
window.uz$md = {};
function uz$e(c, m, p, isSync, module){
? ? param = {};
? ? param.cbId = -1;? ? //-1 表示沒有回調(diào)函數(shù)
? ? newP = [];
? ? var str = Object.prototype.toString.call(p);
? ? if (str == "[object Arguments]" && p.length > 0) {
? ? ? ? p = Array.from(p);
? ? ? ? for (var index = 0; index < p.length;index ++) {
? ? ? ? ? ? node = p[index];
? ? ? ? ? ? str = Object.prototype.toString.call(node);
? ? ? ? ? ? if (str == "[object Function]") {
? ? ? ? ? ? ? ? param.cbId = uz$cb.id ++;
? ? ? ? ? ? ? ? uz$cb.fn[param.cbId] = node;
? ? ? ? ? ? ? ? newP.push(str);
? ? ? ? ? ? }else {
? ? ? ? ? ? ? ? newP.push(node);
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? param.param = newP;
? ? /*
? ? if (p.length === 1) {
? ? ? ? var p0 = p[0];
if (Object.prototype.toString.call(p0) === "[object Object]") {
? ? ? ? ? ? param = p0;
? ? ? ? } else if (typeof p0 === "function") {
? ? ? ? ? ? param.cbId = uz$cb.id++;
? ? ? ? ? ? uz$cb.fn[param.cbId] = p0;
? ? ? ? }
? ? } else if (p.length === 2) {
? ? ? ? var p0 = p[0];
? ? ? ? var p1 = p[1];
? ? ? ? if (Object.prototype.toString.call(p0) === "[object Object]") {
? ? ? ? ? ? param = p0;
? ? ? ? }
? ? ? ? if (typeof p1 === "function") {
? ? ? ? ? ? param.cbId = uz$cb.id++;
? ? ? ? ? ? uz$cb.fn[param.cbId] = p1;
? ? ? ? }
}
? ? */
? ? var message = {};
? ? message.class = c;
? ? message.method = m;
? ? message.param = param;
? ? message.isSync =? false;
? ? message.module = module;
? ? window.webkit.messageHandlers.nativeAndroidOrIos.postMessage(message);
};
function uz$shift() {
? ? if (uz$q.c.length > 0) {
? ? ? ? uz$q.c.shift();
? ? }
? ? uz$q.flag = true;
};
$object_define_placeholder$; //對象定義點位符
nativeAndroidOrIos.require = function(name, cb) {
? ? var module = uz$md[name];
? ? if (!module && nativeAndroidOrIos.useJavaScriptCore) {
? ? ? ? var moduleInfo = nativeAndroidOrIos.getModule({name:name, sync:true});
? ? ? ? if (moduleInfo) {
? ? ? ? ? ? var name = moduleInfo.name;
? ? ? ? ? ? var className = moduleInfo.class;
? ? ? ? ? ? var methods = moduleInfo.methods;
? ? ? ? ? ? var syncMethods = moduleInfo.syncMethods;
? ? ? ? ? ? uz$md[name] = {};
? ? ? ? ? ? if (methods && Object.prototype.toString.call(methods) == '[object Array]') {
? ? ? ? ? ? ? ? for (var i=0;i<methods.length;i++) {
? ? ? ? ? ? ? ? ? ? (function() {
? ? ? ? ? ? ? ? ? ? ? ? var method = methods[i];
? ? ? ? ? ? ? ? ? ? ? ? uz$md[name][method] = function() {
? ? ? ? ? ? ? ? ? ? ? ? ? ? return uz$e(className, method, arguments, false, name);
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? })();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? if (syncMethods && Object.prototype.toString.call(syncMethods) == '[object Array]') {
? ? ? ? ? ? ? ? for (var i=0;i<syncMethods.length;i++) {
? ? ? ? ? ? ? ? ? ? (function() {
? ? ? ? ? ? ? ? ? ? ? ? var method = syncMethods[i];
? ? ? ? ? ? ? ? ? ? ? ? uz$md[name][method] = function() {
? ? ? ? ? ? ? ? ? ? ? ? ? ? return uz$e(className, method, arguments, true, name);
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? })();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? module = uz$md[name];
? ? ? ? }
? ? }
? ? if (module) {
? ? ? ? return module;
? ? } else {
? ? ? ? if (cb) {
? ? ? ? ? ? cb('undefined', {code:1,msg:name+' module not found'});
? ? ? ? } else {
? ? ? ? ? ? return null;
? ? ? ? }
? ? }
}
$method_define_placeholder$; //函數(shù)定義占位符
//var uzmeta = window.document.getElementsByTagName("meta");
//for(var i=0;i<uzmeta.length;i++){
//? ? var name = uzmeta[i].getAttribute('name');
//? ? var content = uzmeta[i].getAttribute('content');
//? ? if (name && name=='viewport' && content){
//? ? ? ? content = content.replace(/width=\d{1,}/,'width=device-width');
//? ? ? ? content = content.replace('width=device-width','width=device-width');
//? ? ? ? uzmeta[i].setAttribute('content',content);
//? ? }
//}
//var uzmeta = window.document.getElementsByTagName("meta");
//for(var i=0;i<uzmeta.length;i++) {
//? ? var name = uzmeta[i].getAttribute('name');
//? ? var content = uzmeta[i].getAttribute('content');
//? ? if (name && name=='viewport' && content){
//? ? ? ? content = content+',user-scalable=0';
//? ? ? ? uzmeta[i].setAttribute('content',content);
//? ? }
//}
document.documentElement.style.webkitTouchCallout = 'none';
document.documentElement.style.webkitUserSelect = 'none';
/*
window.alert = function(arg) {
? ? var msg;
? ? if (arg === null) {
? ? ? ? msg = 'null';
? ? } else if (arg === undefined) {
? ? ? ? msg = 'undefined';
? ? } else {
? ? ? ? msg = arg.toString();
? ? }
? ? nativeAndroidOrIos.alert({
? ? ? ? title:'',
? ? ? ? msg:msg,
? ? ? ? buttons:['好']
? ? });
}
*/
var originalFunc_onerror = window.onerror;
window.onerror = function(message, url, line) {
? ? var param = {};
? ? param.message = message;
? ? param.url = url;
? ? param.line = line;
? ? originalFunc_onerror.apply(window, arguments);
}
function getContentFromArg(arg){
? ? var content;
? ? var args = Array.prototype.slice.call(arg);
? ? if (args.length >= 1) {
? ? ? ? if (args[0] === null) {
? ? ? ? ? ? args[0] = 'null';
? ? ? ? }
? ? ? ? if (args[0] === undefined) {
? ? ? ? ? ? args[0] = 'undefined';
? ? ? ? }
? ? ? ? args[0] = args[0].toString();
? ? }
? ? if (args.length > 1) {
? ? ? ? var i = 1;
? ? ? ? if (args[0].indexOf('%c') == 0) {
? ? ? ? ? ? args[0] = args[0].replace(/%c/,'');
? ? ? ? ? ? i = 2;
? ? ? ? }
? ? ? ? for (; i<args.length; i++) {
? ? ? ? ? ? if (/%s|%d|%i|%o/.test(args[0])) {
? ? ? ? ? ? ? ? args[0] = args[0].replace(/%s|%d|%i|%o/, args[i]);
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? if (i < args.length) {
? ? ? ? ? ? args[0] = args[0]+' '+args.slice(i).join(' ');
? ? ? ? }
? ? ? ? content = args[0];
? ? } else if (args.length == 1) {
? ? ? ? content = args[0];
? ? } else {
? ? ? ? content = '';
? ? }
? ? return content;
}
var originalFunc_log = console.log;
console.log = function() {
? ? var content = getContentFromArg(arguments);
? ? var param = {};
? ? param.method = 'log';
? ? param.content = content;
? ? originalFunc_log.apply(console, arguments);
}
var originalFunc_info = console.info;
console.info = function() {
? ? var content = getContentFromArg(arguments);
? ? var param = {};
? ? param.method = 'info';
? ? param.content = content;
? ? originalFunc_info.apply(console, arguments);
}
var originalFunc_debug = console.debug;
console.debug = function() {
? ? var content = getContentFromArg(arguments);
? ? var param = {};
? ? param.method = 'debug';
? ? param.content = content;
? ? originalFunc_debug.apply(console, arguments);
}
var originalFunc_warn = console.warn;
console.warn = function() {
? ? var content = getContentFromArg(arguments);
? ? var param = {};
? ? param.method = 'warn';
? ? param.content = content;
? ? originalFunc_warn.apply(console, arguments);
}
var originalFunc_error = console.error;
console.error = function() {
? ? var content = getContentFromArg(arguments);
? ? var param = {};
? ? param.method = 'error';
? ? param.content = content;
? ? originalFunc_error.apply(console, arguments);
}
var uzAttempCheckTimes = 0;
function uzCheckApiready() {
? ? if (uzAttempCheckTimes < 50) {
? ? ? ? if (typeof(apiready) === 'function') {
? ? ? ? ? ? apiready();
? ? ? ? } else {
? ? ? ? ? ? uzAttempCheckTimes++;
? ? ? ? ? ? setTimeout('uzCheckApiready()', 100);
? ? ? ? }
? ? }
}
uzCheckApiready();
(function(){
var MAX_MOVE = 5;
var SELECTOR = "tapmode";
function uz_addTouchedClass(node, clas) {
? ? if (node && clas) {
? ? ? ? var list = clas.split(' ');
? ? ? ? for (var i=0;i<list.length;i++) {
? ? ? ? ? ? var classItem = list[i];
? ? ? ? ? ? if (uz_isString(classItem) && classItem.length>0) {
? ? ? ? ? ? ? ? node.classList.add(classItem.trim());
? ? ? ? ? ? }
? ? ? ? }
? ? }
};
function uz_removeTouchedClass(node) {
? ? if (node && node.clicker) {
? ? var clas = node.clicker.clas;
? ? if (clas) {
? ? ? ? ? ? var list = clas.split(' ');
? ? ? ? ? ? for (var i=0;i<list.length;i++) {
? ? ? ? ? ? ? ? var classItem = list[i];
? ? ? ? ? ? ? ? if (uz_isString(classItem) && classItem.length>0) {
? ? ? ? ? ? ? ? ? ? node.classList.remove(classItem.trim());
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? }
? ? };
};
var Clicker = function(){};
function parseTapmode(){
var nodes = document.querySelectorAll('[' + SELECTOR + ']');
? if (nodes) {
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i];
? ? ? ? ? ? if (!node.uzonclick) {
? ? ? ? ? ? ? ? if (node.onclick) {
? ? ? ? ? ? ? ? ? ? node.uzonclick = node.onclick;
? ? ? ? ? ? ? ? ? ? node.onclick = null;
? ? ? ? ? ? ? ? ? ? node.addEventListener('touchstart', uz_handStart, false);
? ? ? ? ? ? ? ? ? ? node.addEventListener('touchmove', uz_handMove, false);
? ? ? ? ? ? ? ? ? ? node.addEventListener('touchend', uz_handEnd, false);
? ? ? ? ? ? ? ? ? ? node.addEventListener('touchcancel', uz_handCancel, false);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
}
? }
};
function uz_isDisabled(e) {
? ? var node = e.currentTarget;
? ? return node.disabled;
};
function uz_isString(str) {
? ? return (typeof str == 'string');
};
function uz_handStart(e) {
? ? if (nativeAndroidOrIos.isScrolling) {
? ? ? ? return;
? ? }
? ? if (uz_isDisabled(e)) {
? ? ? ? return;
? ? }
? ? var node = e.currentTarget;
? ? var clicker = new Clicker();
? ? clicker.X = e.touches[0].clientX;
? ? clicker.Y = e.touches[0].clientY;
? ? clicker.downTime = e.timeStamp;
? ? var clas = node.getAttribute(SELECTOR);
? ? if (!uz_isString(clas)) {
? ? ? ? clas = '';
? ? }
? ? clas = clas.trim();
? ? clicker.clas = clas;
? ? node.clicker = clicker;
? ? uz_addTouchedClass(node, clas);
};
function uz_handMove(e) {
? ? if (uz_isDisabled(e)) {
? ? ? ? return;
? ? }
? ? var node = e.currentTarget;
? ? var clicker = node.clicker;
? ? if (!clicker) {
? ? ? ? return;
? ? }
? ? var x = e.touches[0].clientX, y = e.touches[0].clientY;
? ? if (Math.abs(x - clicker.X) > MAX_MOVE || Math.abs(y - clicker.Y) > MAX_MOVE) {
? ? ? ? uz_reset(node, true);
? ? }
};
function uz_handEnd(e) {
? ? if (uz_isDisabled(e)) {
? ? ? ? return;
? ? }
? ? var node = e.currentTarget;
? ? uz_reset(node);
? ? if (!nativeAndroidOrIos.didShowExitAction) {
? ? ? ? uz_fire(e, node);
? ? }
};
function uz_handCancel(e) {
? ? var node = e.currentTarget;
? ? uz_reset(node, true);
};
function uz_fire(e, node) {
? ? if (node.uzonclick) {
? ? ? ? var clicker = node.clicker;
? ? ? ? if (clicker) {
? ? ? ? ? ? e.preventDefault();
? ? ? ? ? ? node.uzonclick.call(node, e);
? ? ? ? ? ? node.clicker = null;
? ? ? ? }
? ? }
};
function uz_reset(node, del) {
? ? uz_removeTouchedClass(node);
? ? if (del) {
? ? node.clicker = null;
? ? }
};
parseTapmode();
})();
//
//
//
STWKUserContentController.m
@interface STWKUserContentController()<WKScriptMessageHandler>
@property (nonatomic,strong) NSMutableDictionary? ? *delegateInstanceMap; //保存代理實例的字典
@end
@implementation STWKUserContentController
- (instancetype)init {
? ? if (self = [super init]) {
? ? ? ? _delegateInstanceMap = [NSMutableDictionary dictionary];
? ? ? ? [self injectJS];
? ? }
? ? return self;
}
/**
獲取一個類的方法列表,并生成js中方法定義
@param classes 原生類名
@param level js中類層次定義,
@return 返回一個類在js中的定義
*/
- (NSString *)methodByClass:(Class)classes level:(NSString *)level {
? ? NSMutableString *result = [NSMutableString string];
? ? unsigned int count;
? ? __unsafe_unretained Protocol **protocolList = class_copyProtocolList(classes, &count);
? ? for (int i = 0;i < count;i++) {
? ? ? ? Protocol *protocol = protocolList[i];
? ? ? ? unsigned int methodCount = 0;
? ? ? ? struct objc_method_description *method_description_list = protocol_copyMethodDescriptionList(protocol, YES, YES, &methodCount);
? ? ? ? for (int j = 0; j < methodCount ; j ++)
? ? ? ? {
? ? ? ? ? ? struct objc_method_description description = method_description_list[j];
? ? ? ? ? ? NSString *name = NSStringFromSelector(description.name);
? ? ? ? ? ? NSRange range = [name rangeOfString:@":"];
? ? ? ? ? ? if (NSNotFound != range.location) {
? ? ? ? ? ? ? ? name = [name substringToIndex:range.location ];
? ? ? ? ? ? }
? ? ? ? ? ? NSString *str = [NSString stringWithFormat:
? ? ? ? ? ? ? ? ? ? ? ? ? ? @"%@.%@ = function() {\n \
? ? ? ? ? ? ? ? ? ? ? ? ? ? return uz$e('%@', '%@', arguments, false, 'api');\n \
? ? ? ? ? ? ? ? ? ? ? ? ? ? }\n\n",level,name,classes,name];
? ? ? ? ? ? [result appendString:str];
? ? ? ? }
? ? ? ? free(method_description_list);
? ? }
? ? free(protocolList);
? ? /*
? ? Method *methods = class_copyMethodList(classes, &count);
? ? for (int i = 0; i < count; i++) {
? ? ? ? Method method = methods[i];
? ? ? ? SEL selector = method_getName(method);
? ? ? ? NSString *name = NSStringFromSelector(selector);
? ? ? ? NSRange range = [name rangeOfString:@":"];
? ? ? ? if (NSNotFound != range.location) {
? ? ? ? ? ? name = [name substringToIndex:range.location ];
? ? ? ? }
? ? ? ? NSString *str = [NSString stringWithFormat:
? ? ? ? ? ? ? ? ? ? ? ? @"%@.%@ = function() { \
? ? ? ? ? ? ? ? ? ? ? ? return uz$e('%@', '%@', arguments, false, 'api'); \
? ? ? ? ? ? ? ? ? ? ? ? }",level,name,classes,name];
? ? ? ? [result appendString:str];
? ? }
? ? free(methods);
? ? */
? ? return result;
}
- (id)nativeInstanceWithLevel:(NSString *)level {
? ? return nil;
}
- (NSArray *)arrayOfInjectClass {
? ? return @[@{@"level":@"window.nativeAndroidOrIos",
? ? ? ? ? ? ? @"classes":@"nativeAndroidOrIosContext"},
? ? ? ? ? ? ];
}
//根據(jù)類名返回實例對象
- (instancetype)instanceWithClassName:(NSString *)strClass {
? ? id instance = [_delegateInstanceMap objectForKey:strClass];
? ? if ( !instance ) {
? ? ? ? Class classes = NSClassFromString(strClass);
? ? ? ? instance = [[classes alloc] init];
? ? }
? ? return instance;
}
#pragma mark - js注入 -
- (void)injectJS {
? ? [self addScriptMessageHandler:self name:@"nativeAndroidOrIos"];
? ? NSString *ajs = [[NSBundle bundleForClass:[self class]] pathForResource:@"a" ofType:@"js"];
? ? NSString *jsStr = [NSString stringWithContentsOfFile:ajs encoding:NSUTF8StringEncoding error:nil];
? ? NSMutableString *jsContent = [NSMutableString stringWithString:jsStr];
? ? NSArray *arrays = [self arrayOfInjectClass];
? ? //組合類聲明,及函數(shù)聲明字符串
? ? NSMutableString *strLevel = [NSMutableString string];
? ? NSMutableString *strFuncDef = [NSMutableString string];
? ? for (int i = 0; i < [arrays count];i ++) {
? ? ? ? NSString *level = arrays[i][@"level"];
? ? ? ? NSString *strCls = arrays[i][@"classes"];
? ? ? ? Class classes = NSClassFromString(strCls);
? ? ? ? id instance = [[classes alloc] init];
? ? ? ? [_delegateInstanceMap setObject:instance forKey:strCls];
? ? ? ? [strLevel appendFormat:@"%@={};\n",level];
? ? ? ? [strFuncDef appendString:[self methodByClass:classes
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? level:level]];
? ? }
? ? //替換a.js中,對象聲明及函數(shù)定義
? ? NSString *stringJavaScript = [jsContent stringByReplacingOccurrencesOfString:@"$object_define_placeholder$;" withString:strLevel];
? ? stringJavaScript = [stringJavaScript stringByReplacingOccurrencesOfString:@"$method_define_placeholder$;" withString:strFuncDef];
? ? //
? ? WKUserScript *script = [[WKUserScript alloc] initWithSource:stringJavaScript injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
? ? [self addUserScript:script];
? ? //
? ? WKUserScript * cookieScript = [[WKUserScript alloc] initWithSource: [self readCurrentCookie] injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
? ? [self addUserScript:cookieScript];
}
//讀取cookie信息
- (NSString *)readCurrentCookie {
? ? return @"";
? ? NSMutableString *cookieValue = [NSMutableString stringWithFormat:@""];
? ? NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
? ? for (NSHTTPCookie *cookie in [cookieJar cookies]) {
? ? ? ? [cookieValue appendString:[NSString stringWithFormat:@"document.cookie='%@';",cookie.getCookieString]];
? ? }
? ? return cookieValue;
}
//
- (void)onResultCallBack:(AndroidIosNativeBase *)target
? ? ? ? ? ? ? ? ? ? sign:(NSMethodSignature *)sign
? ? ? ? ? ? ? ? ? ? inv:(NSInvocation *)inv {
? ? //獲取返回值類型
? ? const char * returnValueType = sign.methodReturnType;
? ? //聲明一個返回值變量
? ? __autoreleasing id returnValue; //此處一定要為__autoreleasing否則會crash
? ? BOOL bVoidReture = NO;
? ? NSString *strReturnValue;
? ? //如果沒有返回值,也就是消息聲明為void,那么returnValue = nil
? ? if (!strcmp(returnValueType, @encode(void))) {
? ? ? ? NSLog(@"沒有返回值,即返回值類型為void");
? ? ? ? returnValue = nil;
? ? ? ? bVoidReture = YES;
? ? }else if (!strcmp(returnValueType, @encode(id))){
? ? ? ? //如果返回值為對象,那么為變量賦值
? ? ? ? NSLog(@"返回值類型為對象");
? ? ? ? [inv getReturnValue:&returnValue];
? ? ? ? if (!returnValue) {
? ? ? ? ? ? strReturnValue = @"null";
? ? ? ? }
? ? ? ? else {
? ? ? ? ? ? if ([returnValue isKindOfClass:[NSString class]]) {
? ? ? ? ? ? ? ? strReturnValue = returnValue;
? ? ? ? ? ? }else {
? ? ? ? ? ? ? ? @throw [NSException exceptionWithName:@"返回值異常" reason:@"未轉(zhuǎn)換的返回值類型" userInfo:returnValue];
? ? ? ? ? ? }
? ? ? ? }
? ? }else {
? ? ? ? //如果返回值為普通類型,如NSInteger, NSUInteger ,BOOL等
? ? ? ? NSLog(@"返回類型為普通類型");
? ? ? ? //首先獲取返回值長度
? ? ? ? NSUInteger returnValueLenth = sign.methodReturnLength;
? ? ? ? //根據(jù)長度申請內(nèi)存
? ? ? ? void * retValue = (void *)malloc(returnValueLenth);
? ? ? ? //為retValue賦值
? ? ? ? [inv getReturnValue:retValue];
? ? ? ? if (!strcmp(returnValueType, @encode(BOOL))) {
? ? ? ? ? ? returnValue = [NSNumber numberWithBool:*((BOOL *)retValue)];
? ? ? ? ? ? BOOL bRet = returnValue;
? ? ? ? ? ? strReturnValue = [NSString stringWithFormat:@"%@",(bRet ? @"true":@"false")];
? ? ? ? }else if (!strcmp(returnValueType, @encode(NSInteger))){
? ? ? ? ? ? returnValue = [NSNumber numberWithInteger:*((NSInteger *) retValue)];
? ? ? ? ? ? strReturnValue = [NSString stringWithFormat:@"%ld",returnValue];
? ? ? ? }
? ? }
? ? //函數(shù)有返回值
? ? if (!bVoidReture && [target isKindOfClass:[AndroidIosNativeBase class]]) {
? ? ? ? AndroidIosNativeBase *native = (AndroidIosNativeBase *)target;
? ? ? ? [native onResultCallBack:@"[Function]" value:strReturnValue];
? ? }
}
//根據(jù)類名,方法名,參數(shù)個數(shù)查找合適的方法并執(zhí)行
- (void)nativeOcMethod:(WKWebView *)webView classes:(NSString *)classes method:(NSString *)strMethod args:(id)param {
? ? unsigned int count;
? ? Class classz = NSClassFromString(classes);
? ? Method *methods = class_copyMethodList(classz, &count);
? ? for (int i = 0; i < count; i++) {
? ? ? ? Method method = methods[i];
? ? ? ? SEL selector = method_getName(method);
? ? ? ? NSString *name = NSStringFromSelector(selector);
? ? ? ? NSRange range = [name rangeOfString:@":"];
? ? ? ? if (NSNotFound != range.location) {
? ? ? ? ? ? name = [name substringToIndex:range.location ];
? ? ? ? }
? ? ? ? if ([name isEqualToString:strMethod]) { //找到對應方法名
? ? ? ? ? ? unsigned int argN = method_getNumberOfArguments(method);
? ? ? ? ? ? if ([param isKindOfClass:[NSDictionary class]]) {
? ? ? ? ? ? ? ? NSArray *args = [param objectForKey:@"param"];
? ? ? ? ? ? ? ? if (argN - 2 ==? [args count] ) {? ? //簡單判斷參數(shù)個數(shù)相等,則認為是同一方法
? ? ? ? ? ? ? ? ? ? id target =? [self instanceWithClassName:classes];
? ? ? ? ? ? ? ? ? ? if ([target isKindOfClass:[AndroidIosNativeBase class]]) {
? ? ? ? ? ? ? ? ? ? ? ? ((AndroidIosNativeBase *)target).cbId = [[param objectForKey:@"cbId"] integerValue];
? ? ? ? ? ? ? ? ? ? ? ? ((AndroidIosNativeBase *)target).webView = webView;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? NSMethodSignature *singture = [classz instanceMethodSignatureForSelector:selector];
? ? ? ? ? ? ? ? ? ? NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:singture];
? ? ? ? ? ? ? ? ? ? [invocation setTarget:target];
? ? ? ? ? ? ? ? ? ? [invocation setSelector:selector];
? ? ? ? ? ? ? ? ? ? //index從2開始
? ? ? ? ? ? ? ? ? ? for (int i = 0;i <[args count];i++) {
? ? ? ? ? ? ? ? ? ? ? ? id value = args[i];
? ? ? ? ? ? ? ? ? ? ? ? [invocation setArgument:&value atIndex:i + 2];
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? [invocation retainArguments];? //retain參數(shù) 防止被dealloc
? ? ? ? ? ? ? ? ? ? [invocation invoke];
? ? ? ? ? ? ? ? ? ? //取消返回值
? ? ? ? ? ? ? ? ? ? //[self onResultCallBack:target sign:singture inv:invocation];
? ? ? ? ? ? ? ? ? ? return;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? NSLog(@"method_getName:%@",name);
? ? }
}
//
#pragma mark - WKScriptMessageHandler -
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
? ? if ([message.name isEqualToString:@"nativeAndroidOrIos"]) {
? ? ? ? if ([message.body isKindOfClass:[NSDictionary class]]) {
? ? ? ? ? ? NSDictionary *body = message.body;
? ? ? ? ? ? NSString *method = [body objectForKey:@"method"];
? ? ? ? ? ? NSString *class = [body objectForKey:@"class"];
? ? ? ? ? ? NSDictionary *params = [body objectForKey:@"param"];//參數(shù)
? ? ? ? ? ? if ([params isKindOfClass:[NSDictionary class]]) {
? ? ? ? ? ? ? ? [self nativeOcMethod:message.webView classes:class method:method args:params];
? ? ? ? ? ? }
? ? ? ? }
? ? }
}
@end