iOS 9下UniWebView播放本地存储音频失败问题咨询
我刚好遇到过类似的坑,iOS 9的WKWebView在处理本地资源时确实有不少和高版本不一样的限制,尤其是跨目录资源访问这块,刚好能给你梳理清楚:
核心问题:iOS 9的WKWebView沙盒权限限制
iOS 9里,WKWebView对本地文件的访问沙盒规则比iOS 10+严格得多。当你加载本地HTML后,尝试引用同目录下子文件夹的音频时,会被系统悄悄拦截——这就是为什么Safari调试看不到明确错误的原因,这类权限级别的拦截很多时候不会抛出详细错误信息。
具体差异与规则
- 在iOS 10及以上,苹果放宽了限制,允许WKWebView通过相对路径直接访问同目录下子文件夹的资源;
- 但iOS 9中,WKWebView默认的沙盒访问范围仅局限于你加载的HTML文件所在的直接目录,子文件夹的资源不在允许访问的范围内,哪怕是相对路径也不行。
可行的解决办法
这里给你几个实用的方案,按实现复杂度排序:
1. 临时快速方案:调整资源位置
最简单的办法就是把音频文件从子文件夹移到和HTML文件同一个目录下,用相对路径直接引用,iOS 9就能正常加载播放了。这个方案适合快速验证问题,或者资源结构不复杂的场景。
2. 显式开启文件访问权限(必做步骤)
先检查你的WKWebView配置,iOS 9中必须手动开启allowsFileAccessFromFileURLs,否则哪怕路径正确也会被拦截。如果用UniWebView的话,需要自定义WKWebConfiguration传入:
WKWebConfiguration *webConfig = [[WKWebConfiguration alloc] init]; // 开启本地文件访问权限 webConfig.allowsFileAccessFromFileURLs = YES; // 如果是内嵌播放音频,还需要开启这个 webConfig.allowsInlineMediaPlayback = YES; // 用自定义配置初始化UniWebView UniWebView *myWebView = [[UniWebView alloc] initWithFrame:self.view.bounds configuration:webConfig];
这个步骤很容易被忽略,很多iOS 9的本地资源问题都是因为没开这个权限。
3. 以目录为单位加载HTML
不要直接加载单个HTML文件的URL,而是先构造整个资源目录的URL,再加载其中的HTML文件。这样WKWebView会把整个目录作为沙盒访问范围,就能正常访问子文件夹的资源了:
// 假设你的HTML和子文件夹都在webContent目录下 NSString *resourceDirPath = [[NSBundle mainBundle] pathForResource:@"webContent" ofType:nil]; NSURL *dirURL = [NSURL fileURLWithPath:resourceDirPath isDirectory:YES]; NSURL *htmlURL = [dirURL URLByAppendingPathComponent:@"index.html"]; [myWebView loadURL:htmlURL];
4. 自定义NSURLProtocol拦截请求(兼容iOS 9)
如果上面的方案都不适合你的资源结构,可以用NSURLProtocol来拦截WKWebView的资源请求,手动从沙盒中读取子文件夹的音频文件并返回数据。这个方案稍微复杂,但灵活性最高:
- 自定义一个
NSURLProtocol子类,在canInitWithRequest:方法中识别音频资源的请求; - 在
startLoading方法中,根据请求的路径从本地沙盒找到对应的音频文件,读取数据后封装成NSURLResponse返回给WKWebView; - 记得在APP启动时注册这个自定义Protocol。
额外检查点
最后别忘了确认你的音频文件已经正确打包进APP:在Xcode中选中目标,进入Build Phases -> Copy Bundle Resources,确保音频文件和子文件夹都在列表里,避免因为资源没打包导致的加载失败。
内容的提问来源于stack exchange,提问作者Dalius Grazinskis

