使用WKWebView加载3D模型,3D模型是使用webGL开发的,考虑到网络问题,采用本地化的方式,将3D模型数据下载到本地沙盒,将JS代码放入到工程目录下,再使用WKWebView加载index.html。
问题一:WKWebView访问index.html
由于JS代码中是通过文件路径找访问其他JS文件,所以在将js代码导入到项目中时,要创建实体文件夹才能够正常访问,如下图:
问题二:WKWebView无权限访问本地文件
1、访问本地文件使用的是file://协议,由于WKWebView的安全机制,会报一些错无法访问到。需要打开webView的file://协议访问权限,设置`allowFileAccessFromFileURLs`为`true`。
2、如果出现跨域的报错,也可以通过设置`allowUniversalAccessFromFileURLs`为`true`来解决。
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
// 解决HTML请求跨域
[config setValue:@(true) forKey:@"allowUniversalAccessFromFileURLs"];
WKPreferences *preferences = [[WKPreferences alloc] init];
// 打开web访问本地文件权限
[preferences setValue:@(true) forKey:@"allowFileAccessFromFileURLs"];
config.preferences = preferences;问题三:WKWebView访问沙盒文件
WKWebView无法访问Documents文件夹下的内容,只能访问tmp文件夹,因为下载的文件是放在Documents文件夹下的,所以有下面两个解决方案:
方案一、将文件拷贝到tmp文件夹下访问
通过文件管理类`NSFileManager`进行文件的拷贝,但是由于下载的文件比较大,并且会有文件更新的情况,如果每次都拷贝的话,拷贝的时间比较长,很影响用户体验。
+ (void)copyFileFromPath:(NSString *)sourcePath toPath:(NSString *)toPath {
NSFileManager *fileManager = [NSFileManager defaultManager];
// 判断目标位置 id 文件夹是否存在
if ([fileManager fileExistsAtPath:toPath]) {
// 存在,先移除
[fileManager removeItemAtPath:toPath error:nil];
}
// 不存在 先创建 目标位置 id 文件夹
BOOL toSuccess = [fileManager createDirectoryAtPath:toPath withIntermediateDirectories:YES attributes:nil error:nil];
if (toSuccess) {
// 获取fromPath文件路径下所有文件
NSArray* array = [fileManager contentsOfDirectoryAtPath:sourcePath error:nil];
for(int i = 0; i<[array count]; i++) {
NSString *fullPath = [sourcePath stringByAppendingPathComponent:[array objectAtIndex:i]];
NSString *fullToPath = [toPath stringByAppendingPathComponent:[array objectAtIndex:i]];
// 判断是否存在并且为文件夹
BOOL isFolder = NO;
BOOL isExist = [fileManager fileExistsAtPath:fullPath isDirectory:&isFolder];
if (isExist && isFolder) {
// 存在并且是文件夹,在toPath下创建
[fileManager createDirectoryAtPath:fullToPath withIntermediateDirectories:YES attributes:nil error:nil];
[self copyFileFromPath:fullPath toPath:fullToPath];
} else if (isExist && !isFolder) {
NSError *err = nil;
[fileManager copyItemAtPath:fullPath toPath:fullToPath error:&err];
} else {
NSLog(@"未找到源文件");
}
}
}
}方案二、拦截file://协议,使用原生获取本地沙盒文件,再将数据传给JS
该方案的具体实现可参考另一篇文章《WKWebView实现请求拦截,http/https/file等》
问题四:加载本地3D模型的时候,无法显示
在拦截file://请求之后,需要回传给webView请求任务一个response,在生成response的时候有两种方式`NSURLResponse`和`NSHTTPURLResponse`两种方式,使用`NSHTTPURLResponse`方式生成可以正常加载。(可参考另一篇文章《WKWebView实现请求拦截,http/https/file等》)
版权声明:本文为colrying原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。