iOS加载本地HTML

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/czb1n/article/details/70212280

目标:读取本地的HTML文件来展示H5页面。

  • HTML文件会需要根据URL中不同的Hash Tag来显示不同的页面。例如#!/register显示注册页,#!/login显示登录页等等。
  • HTML文件还需要根据URL传入的参数请求数据。

iOS8以后,苹果推出了新框架WebKit。所以分别用UIWebViewWKWebView来实现看看。
以下仅当HTML文件的文件名为index.html

WebView调试方法是在模拟器显示WebView之后,打开Safari的"开发"Tab的Simulator。

UIWebView

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
NSString *htmlString = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
NSURL *url = [[NSURL alloc] initWithString:filePath];
[self.webView loadHTMLString:htmlString baseURL:url];

以上是把HTML文件读取成字符串再加载到WebView中,这时传递的URL还没有带上Hash Tag和参数。

除了加载HTML字符串以外还可以直接加载文件路径的请求:

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
NSURL *url = [[NSURL alloc] initWithString:filePath];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:request];

那么要在URL上加上Hash Tag和传入参数很简单,只需要在URL上拼接上去就可以了。

NSString *component = @"#!/login?id=1&user=admin";
NSString *urlString = [filePath stringByAppendingString:component];
NSURL *url = [[NSURL alloc] initWithString:urlString];

但是这样有一个问题就是URL传入的时候一些特殊符号会有编码问题。

NSString *encodedComponent = (NSString *)CFBridgingRelease(
            CFURLCreateStringByAddingPercentEscapes(
            kCFAllocatorDefault,
            (CFStringRef)component,
            (CFStringRef)@"!$&'()*+,-./:;=?@_~%#",
            NULL,
            kCFStringEncodingUTF8
            )
            );
NSString *urlString = [filePath stringByAppendingString:component];
NSURL *url = [[NSURL alloc] initWithString:urlString];

到此就可以满足上述的目标了。
不过这里有一个其他问题,UIWebView会有内存占用非常高而且不释放导致溢出的问题,这里也顺便记录一下普遍的解决方法。

当收到系统的内存告警时,清除所有缓存的Response。

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];

    [[NSURLCache sharedURLCache] removeAllCachedResponses];
}

当加载完一个链接之后,系统会把WebKitCacheModelPreferenceKey这个属性设为1,导致内存不会释放。所以实现UIWebViewDelegate中的- (void)webViewDidFinishLoad:(UIWebView *)webView;方法。在加载完一个链接之后把WebKitCacheModelPreferenceKey属性设为0
并禁用WebKitDiskImageCacheEnabledWebKitOfflineWebApplicationCacheEnabled这两个缓存。

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    [[NSUserDefaults standardUserDefaults] setInteger:0 forKey:@"WebKitCacheModelPreferenceKey"];
    [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"WebKitDiskImageCacheEnabled"];
    [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"WebKitOfflineWebApplicationCacheEnabled"];
    [[NSUserDefaults standardUserDefaults] synchronize];
}
- (void)dealloc
{
    [self.webView stopLoading];
    [self.webView removeFromSuperview];
    self.webView = nil;
}

WKWebView

WKWebView速度更快,内存占用少。使用的方法和UIWebView的方法差不多。

列几个关于WKWebView的问题:

  • 使用WKWebView的时候不能用上面的那种方式去拼接URL。
    需要用:
    - (nullable instancetype)initWithString:(NSString *)URLString relativeToURL:(nullable NSURL *)baseURL NS_DESIGNATED_INITIALIZER;
    + (nullable instancetype)URLWithString:(NSString *)URLString relativeToURL:(nullable NSURL *)baseURL;
NSURL *fileUrl = [[NSURL alloc] initWithString:filePath];
NSURL *url = [NSURL URLWithString:encodedComponent relativeToURL:fileUrl];
  • 还有WebKit框架对跨域进行了安全性检查限制,不允许跨域。所以同样的方法可能在UIWebView能获取到数据,在WKWebView却获取不到数据。

这个问题我暂时未想到较好的解决方法,欢迎指教。或许可以把请求部分提到App中,得到数据之后再通过JavaScript传入HTML中。

  • 看到其他资料说WKWebView使用- (nullable WKNavigation *)loadRequest:(NSURLRequest *)request;来读取本地的HTML无法读取成功,后台会出现如下的提示:Could not create a sandbox extension for /

这个我在用模拟器测试的过程中并没有出现相应的错误。

阅读更多 登录后自动展开
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页