ios开发 加载h5字符串

2017-04-17 15:43:05 czb1n 阅读数 18396

目标:读取本地的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 /

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

2017-03-27 16:33:40 sheng_bin 阅读数 5088

iOS中OC加载HTML字符串

最近项目里面遇见了 HTML 字符串,整理如下:


后台返回字符串的样式

在 iOS 中通常加载 HTML 字符串有两种方式

  • 通过 UILabel 加载富文本的方法加载 HTML 字符串
  • 通过 WebView 加载 HTML 字符串
- (void)viewDidLoad {
    [super viewDidLoad];

1.UILabel 加载 HTML 字符串
NSString * str1 = @"<div>Google(中文名:谷歌),是一家美国的跨国科技企业。</div><div>Google由当时在斯坦福大学攻读理工博士的拉里·佩奇和谢尔盖·布卢姆共同创建,因此两人也被称为“Google Guys”。</div><div>1998年9月4日,Google以私营公司的形式创立,设计并管理一个互联网搜索引擎“Google搜索”。</div&gt";
NSString * str2 = @"<p><br></p&gt";
NSString * str3 = @"<p>qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq</p&gt";
//1.将字符串转化为标准HTML字符串
    str1 = [self htmlEntityDecode:str1];
//2.将HTML字符串转换为attributeString
    NSAttributedString * attributeStr = [self attributedStringWithHTMLString:str1];

//3.使用label加载html字符串
    self.label.attributedText = attributeStr;

2.UIWebView 加载HTML字符串
    UIWebView * webView = [[UIWebView alloc]initWithFrame:CGRectMake(20, 300, self.view.frame.size.width - 40, 400)];
    [webView loadHTMLString:str1 baseURL:nil];
    [self.view addSubview:webView];
    self.webView = webView;
}

//将 &lt 等类似的字符转化为HTML中的“<”等 
- (NSString *)htmlEntityDecode:(NSString *)string
{
    string = [string stringByReplacingOccurrencesOfString:@"&quot;" withString:@"\""];
    string = [string stringByReplacingOccurrencesOfString:@"&apos;" withString:@"'"];
    string = [string stringByReplacingOccurrencesOfString:@"&lt;" withString:@"<"];
    string = [string stringByReplacingOccurrencesOfString:@"&gt;" withString:@">"];
    string = [string stringByReplacingOccurrencesOfString:@"&amp;" withString:@"&"]; // Do this last so that, e.g. @"&amp;lt;" goes to @"&lt;" not @"<"

    return string;
}

//将HTML字符串转化为NSAttributedString富文本字符串
- (NSAttributedString *)attributedStringWithHTMLString:(NSString *)htmlString
{
    NSDictionary *options = @{ NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType,
                               NSCharacterEncodingDocumentAttribute :@(NSUTF8StringEncoding) };

    NSData *data = [htmlString dataUsingEncoding:NSUTF8StringEncoding];

    return [[NSAttributedString alloc] initWithData:data options:options documentAttributes:nil error:nil];
}

//去掉 HTML 字符串中的标签
- (NSString *)filterHTML:(NSString *)html
{
    NSScanner * scanner = [NSScanner scannerWithString:html];
    NSString * text = nil;
    while([scanner isAtEnd]==NO)
    {
        //找到标签的起始位置
        [scanner scanUpToString:@"<" intoString:nil];
        //找到标签的结束位置
        [scanner scanUpToString:@">" intoString:&text];
        //替换字符
        html = [html stringByReplacingOccurrencesOfString:[NSString stringWithFormat:@"%@>",text] withString:@""];
    }
    //    NSString * regEx = @"<([^>]*)>";
    //    html = [html stringByReplacingOccurrencesOfString:regEx withString:@""];
    return html;
}

注意 

  • 此处的字符串不是标准的标签的HTML字符串,所以我们首先要调用- (NSString )htmlEntityDecode:(NSString )string 方法将字符串转换成标准的HTML字符串,这样才可以进行HTML字符串的加载
  • 实例的第二个字符串中的内容为空,当用 Label 加载的时候只是两行空白数据,此时可以调用- (NSString )filterHTML:(NSString )html 方法,去掉标签,将HTML字符串转换为常用的字符串样式
2019-05-17 17:43:04 m0_37625794 阅读数 853

在iOS开发过程中,用webView显示富文本内容是很常见的需求,加载富文本时通常还要根据webView的高度动态计算cell的高度(例如我们要在tableView或者collectionView的某个cell上)用webView显示一段富文本信息,通常富文本都是由图文混合的。会不多说,直接商代码。以cell为例

1.先申明一个webView属性,并设置代理

@property (strong,nonatomic) UIWebView *webView;

2.初始化webiew,并给webView一个默认高度

    UIWebView *webView = [[UIWebView alloc] init];

    self.webView = webView;

    self.webView.delegate = self;

    [self.contentView addSubview:webView];

    [webView mas_makeConstraints:^(MASConstraintMaker *make) {

        make.left.equalTo(self.contentView);

        make.top.equalTo(self.contentView);

        make.width.equalTo(self.contentView);

        make.height.equalTo(@10);

    }];

3.在webView的代理方法中执行操作

- (void)webViewDidFinishLoad:(UIWebView *)webView {

        NSString *js = @"function imgAutoFit() { \

        var imgs = document.getElementsByTagName('img'); \

        for (var i = 0; i < imgs.length; ++i) {\

        var img = imgs[i];   \

        img.style.maxWidth = %f;   \

        } \

        }";

        js = [NSString stringWithFormat:js, ScreenW - 20];

        //注入js 到html中

        [webView stringByEvaluatingJavaScriptFromString:js];

        //调用

        [webView stringByEvaluatingJavaScriptFromString:@"imgAutoFit()"];

        

        //获取到webview的高度

        CGFloat webViewHeight = [[webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight"] floatValue];

        [self.webView mas_updateConstraints:^(MASConstraintMaker *make) {

            make.height.mas_equalTo(webViewHeight);

        }];

        if (self.reloadHeightBlock) {

            self.reloadHeightBlock(webViewHeight);

        }

}

reloadHeightBlock是在获取webView高度后传给控制器刷新tableView,webViewHeight高度为该cell对应tableView的高度。

2019-03-14 16:50:00 weixin_30246221 阅读数 76

要加载html字符串,用人说,直接用webView啊!但是,有时候我们只需要显示2行文字,如此少的内容却要在复杂的UI排版中加入一个占用资源较多的webview,得不偿失。这里要说的是,我们其实可以用label即可加载html字符的,用富文本转一下html字符串即可。

//创建UILabel

   _Test_Lbl = [[UILabel alloc] initWithFrame:CGRectMake(10, 100, 200, 200)];
    _Test_Lbl.backgroundColor = [UIColor yellowColor];
    _Test_Lbl.textColor = [UIColor redColor];
    [self.view addSubview:_Test_Lbl];

 

服务端返回的不一定都是纯字符串,有可能是带有HTML标签的
//html字符串转换为富文本

    NSString *html = @"<p style='color:green'>首付<span style='color:#e83c36;'>5000元</span>,提前付<span style='color:red'>3倍月供</span>,月供<span style='color:red'>3000元</span>(48期)</p>";
    NSAttributedString *attStr = [[NSAttributedString alloc] initWithData:[html dataUsingEncoding:NSUnicodeStringEncoding] options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType} documentAttributes:nil error:nil];
 
    _Test_Lbl.attributedText = attStr;

 

//富文本转换为html(最后相当于整个网页代码,会有css等)

    NSDictionary *dic = @{NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType,NSCharacterEncodingDocumentAttribute:@(NSUnicodeStringEncoding)};
    NSData *data = [attStr dataFromRange:NSMakeRange(0, attStr.length) documentAttributes:dic error:nil];
    NSString *htmlstr = [[NSString alloc] initWithData:data encoding:NSUnicodeStringEncoding];

    _Test_Lbl.text = htmlstr;

 

//计算html字符串高度

    //计算html字符串高度
    NSMutableAttributedString *htmlString =[[NSMutableAttributedString alloc] initWithData:[html dataUsingEncoding:NSUTF8StringEncoding] options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute:[NSNumber numberWithInt:NSUTF8StringEncoding]} documentAttributes:NULL error:nil];
    
    [htmlString addAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:14]} range:NSMakeRange(0, htmlString.length)];
    
    CGSize textSize = [htmlString boundingRectWithSize:(CGSize){ScreenWidth - 20, CGFLOAT_MAX} options:NSStringDrawingUsesLineFragmentOrigin context:nil].size;
    
    return textSize.height ;

 

转载于:https://www.cnblogs.com/GJ-ios/p/10531351.html

2015-10-16 11:19:17 woaifen3344 阅读数 13777

原文出自:iOS原生如何加载HTML中img标签的图片

前言

最近iOS App项目中使用Webview加载H5页面比较多,也有不少朋友经常问到这个问题,在这里我也学习学习如何通过iOS原生的方式来加载H5页面中的图片然后让webview显示图片。

相信有很多朋友也遇到过这样的问题,可是很多朋友都没有思路,不知如何入手。今天,刚好学习了一下,并写了一个简单的demo。下面让我们一起来学习一下吧!

本篇文章适合哪些人群阅读?

  • 项目中有类似需求的,而又没有思路的
  • 曾经做过类似需求的,可以参考两者的思想有何异同,比较哪种方式更好
  • 没有做过类似需求,且也没有思路入手的,可以参考学习

注意:本文有Objective-C版和Swift,根据个人情况看相关章节

思路讲解

这里有两种方式可以实现:

  • 直接使用NSData同步加载图片的方式(Swift版用同步实现
  • 通过其他第三方库异步加载图片的方式(ObjC版用异步实现

Swift版代码讲解

下面看看我们的核心代码吧:

let path = NSBundle.mainBundle().pathForResource("test", ofType: "html")
let url = NSURL(fileURLWithPath: path!)

do {
  let html = try String(contentsOfURL: url, encoding: NSUTF8StringEncoding)
  //      print(html)

  // 获取所有img src中的src链接,并将src更改名称
  // 这里直接采用同步获取数据,异步也是一样的道理,为了方便写demo,仅以同步加载图片为例。
  // 另外,这不考虑清除缓存的问题。
  do {
    let regex = try NSRegularExpression(pattern: "<img\\ssrc[^>]*/>", options: .AllowCommentsAndWhitespace)

    let result = regex.matchesInString(html, options: .ReportCompletion, range: NSMakeRange(0, html.characters.count))

    var content = html as NSString
    var sourceSrcs: [String: String] = ["": ""]

    for item in result {
      let range = item.rangeAtIndex(0)

      let imgHtml = content.substringWithRange(range) as NSString
      var array = [""]

      if imgHtml.rangeOfString("src=\"").location != NSNotFound {
        array = imgHtml.componentsSeparatedByString("src=\"")
      } else if imgHtml.rangeOfString("src=").location != NSNotFound {
        array = imgHtml.componentsSeparatedByString("src=")
      }

      if array.count >= 2 {
        var src = array[1] as NSString
        if src.rangeOfString("\"").location != NSNotFound {
          src = src.substringToIndex(src.rangeOfString("\"").location)

          // 图片链接正确解析出来
          print(src)

          // 加载图片
          // 这里不处理重复加载的问题,实际开发中,应该要做一下处理。
          // 也就是先判断是否已经加载过,且未清理掉该缓存的图片。如果
          // 已经缓存过,否则才执行下面的语句。
          let data = NSData(contentsOfURL: NSURL(string: src as String)!)
          let localUrl = self.saveImageData(data!, name: (src as String).md5)

          // 记录下原URL和本地URL
          // 如果用异步加载图片的方式,先可以提交将每个URL起好名字,由于这里使用的是原URL的md5作为名称,
          // 因此每个URL的名字是固定的。
          sourceSrcs[src as String] = localUrl
        }
      }
    }

    for (src, localUrl) in sourceSrcs {
      if !localUrl.isEmpty {
        content = content.stringByReplacingOccurrencesOfString(src as String, withString: localUrl, options: NSStringCompareOptions.LiteralSearch, range: NSMakeRange(0, content.length))
      }
    }

    print(content as String)
    webView.loadHTMLString(content as String, baseURL: url)
  } catch {
    print("match error")
  }
} catch {
  print("load html error")
}

此处省略1000字,完整阅读文章内容,请移步微信公众号阅读。

移步微信公众号阅读全文

源代码

想要下载源代码,请移步github下载,内有Swift版的工程和ObjC版的工程:

https://github.com/CoderJackyHuang/iOSLoadWebViewImage


公众号搜索「iOS开发技术分享」快速关注微信号:iOSDevShares QQ群:324400294

image

iOS 与H5交互

阅读数 4465