webview轉(zhuǎn)wkwebview遇到的問題

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容