这一文章介绍如何通过类目让WKWebView优雅的实现POST请求,为啥说是优雅:
实现POST请求
实现原理是通过一段js函数post表单参数,灵感来源于网上(加载一个带有js函数的空页面,页面加载完成后立刻调用函数发起post请求),使用起来貌似需要在代理里边各种穿插代码,我是觉得使用起来不是很方便。
这里实现主要是采用js交互和runtime结合实现,demo:https://github.com/youlianchun/WKWebView_POST
采用swizzledMethod拦截 -[WKWebView loadRequest:],在理面判断POST Request,然后直接拼接执行js代码块
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [self class];
SEL originalSelector = @selector(loadRequest:);
SEL swizzledSelector = @selector(post_loadRequest:);
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
BOOL success = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
if (success) {
class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
}
-(WKNavigation *)post_loadRequest:(NSURLRequest *)request {
if ([[request.HTTPMethod uppercaseString] isEqualToString:@"POST"]){
NSString *url = request.URL.absoluteString;
NSString *params = [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding];
if ([params containsString:@"="]) {
params = [params stringByReplacingOccurrencesOfString:@"=" withString:@"\":\""];
params = [params stringByReplacingOccurrencesOfString:@"&" withString:@"\",\""];
params = [NSString stringWithFormat:@"{\"%@\"}", params];
}else{
params = @"{}";
}
NSString *postJavaScript = [NSString stringWithFormat:@"\
var url = '%@';\
var params = %@;\
var form = document.createElement('form');\
form.setAttribute('method', 'post');\
form.setAttribute('action', url);\
for(var key in params) {\
if(params.hasOwnProperty(key)) {\
var hiddenField = document.createElement('input');\
hiddenField.setAttribute('type', 'hidden');\
hiddenField.setAttribute('name', key);\
hiddenField.setAttribute('value', params[key]);\
form.appendChild(hiddenField);\
}\
}\
document.body.appendChild(form);\
form.submit();", url, params];
// __block id result = nil;
// __block BOOL isExecuted = NO;
__weak typeof(self) wself = self;
[self evaluateJavaScript:postJavaScript completionHandler:^(id object, NSError * _Nullable error) {
if (error && [wself.navigationDelegate respondsToSelector:@selector(webView:didFailProvisionalNavigation:withError:)]) {
dispatch_async(dispatch_get_main_queue(), ^{
[wself.navigationDelegate webView:wself didFailProvisionalNavigation:nil withError:error];
});
}
// result = object;
// isExecuted = YES;
}];
// while (isExecuted == NO) {
// [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
// }
return nil;
}else{
return [self post_loadRequest:request];
}
}