前言:UIWebView调用远端h5页面,优先加载本地图片、js、css等资源,解决办法就是对请求进行拦截。
服务端代码放在本文后面
客户端需要对NSURLProtocol 的自定义类进行注册,那么所有的webview 对http请求都会被他拦截到;
首先自定义NSURLProtocol类
#import <Foundation/Foundation.h>
#import <CoreFoundation/CoreFoundation.h>
#import <MobileCoreServices/MobileCoreServices.h>
@interface NSURLProtocolCustom : NSURLProtocol
@end
#import "NSURLProtocolCustom.h"
static NSString* const FilteredKey = @"FilteredKey";
@implementation NSURLProtocolCustom
+ (BOOL)canInitWithRequest:(NSURLRequest *)request
{
NSString *extension = request.URL.pathExtension;
BOOL isSource = [@[@"png", @"jpeg", @"gif", @"jpg", @"js", @"css"] indexOfObjectPassingTest:^BOOL(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
return [extension compare:obj options:NSCaseInsensitiveSearch] == NSOrderedSame;
}] != NSNotFound;
return [NSURLProtocol propertyForKey:FilteredKey inRequest:request] == nil && isSource;
}
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request
{
return request;
}
- (void)startLoading
{
NSString *fileName = [super.request.URL.absoluteString componentsSeparatedByString:@"/"].lastObject;
NSLog(@"fileName is %@",fileName);
//这里是获取本地资源路径 如:png,js等
NSString *path = [[NSBundle mainBundle] pathForResource:fileName ofType:nil];
if (!path) {
[self sendResponseWithData:[NSData data] mimeType:nil];
return;
}
//根据路径获取MIMEType
CFStringRef pathExtension = (__bridge_retained CFStringRef)[path pathExtension];
CFStringRef type = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension, NULL);
CFRelease(pathExtension);
//The UTI can be converted to a mime type:
NSString *mimeType = (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass(type, kUTTagClassMIMEType);
if (type != NULL)
CFRelease(type);
//加载本地资源
NSData *data = [NSData dataWithContentsOfFile:path];
[self sendResponseWithData:data mimeType:mimeType];
}
- (void)stopLoading
{
NSLog(@"stopLoading, something went wrong!");
}
- (void)sendResponseWithData:(NSData *)data mimeType:(nullable NSString *)mimeType
{
// 这里需要用到MIMEType
NSURLResponse *response = [[NSURLResponse alloc] initWithURL:super.request.URL
MIMEType:mimeType
expectedContentLength:-1
textEncodingName:nil];
//硬编码 开始嵌入本地资源到web中
[[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
[[self client] URLProtocol:self didLoadData:data];
[[self client] URLProtocolDidFinishLoading:self];
}
@end
其次实现对类的注册
#import "CWWebView.h"
#import "NSURLProtocolCustom.h"
@interface CWWebView ()<UIWebViewDelegate>
@property (nonatomic,strong) UIWebView *myWebView;
@end
@implementation CWWebView
- (void)viewDidLoad {
[super viewDidLoad];
//1.注册自定义类
[NSURLProtocol registerClass:[NSURLProtocolCustom class]];
//2.添加
[self.view addSubview:self.myWebView];
}
- (UIWebView *)myWebView
{
if (!_myWebView) {
_myWebView = [[UIWebView alloc] initWithFrame:self.view.bounds];
_myWebView.backgroundColor = [UIColor redColor];
_myWebView.scalesPageToFit = YES;
_myWebView.delegate = self;
NSURL *url = [[NSURL alloc] initWithString:@"http://139.224.57.105/apptest/app.html"];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
[_myWebView loadRequest:request];
}
return _myWebView;
}
@end
服务端代码
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>测试iOS与JS之间的互调</title>
<style type="text/css">
{
font-size: 40px;
}
</style>
</head>
<body>
<div style="rargin-top: 100px;">
<h1>Test how to use Objective-C call js</h1>
<input type="button" value="Call iOS" οnclick="calliOS('call iOS')">
<input type="button" value="Call JS Alert" οnclick="jsFunc()">
</div>
<div>
<input type="button" value="iOS Call With No JSON" οnclick="callJS()">
<input type="button" value="iOS Call With JSON" οnclick="callJSMsg('iOS Call JS')">
</div>
<div>
<span id="jsParatFuncSpan" style="color:red; font-size:50px;"></span>
</div>
</body>
<script type="text/JavaScript" src="appJs.js"></script>
</html>
function calliOS(Msg) {
var message = {
'method' : 'hello',
'param1' : Msg,
};
window.webkit.messageHandlers.webViewApp.postMessage(message);
}
function callJS() {
var message = {
'method' : 'Call JS',
};
window.webkit.messageHandlers.webViewApp.postMessage(message);
}
function callJSMsg(Msg) {
var message = {
'method' : 'Call JS Msg',
'param1' : Msg,
};
window.webkit.messageHandlers.webViewApp.postMessage(message);
}
function jsFunc() {
alert('Hello World');
}