要在页面中显示自己的布局,比如文字的字体和颜色、图文并排的样式,我们要用iOS SDK的原生UI在app本地搭建,如果一个页面需要在服务器端获取数据的话,我们也要在本地搭建好固定的布局,解析服务器传回的Json数据去进行填充。但是如果一个页面的布局是不固定的话,比如一个web页面,用HTML与CSS封装,我们通常会使用UIWebView进行处理。但是这样处理等于是是把某一个页面纯粹当成了Web页面进行渲染,在移动app开发中,这样的情况被称为“非原生”,不仅会失去渲染速度和交互体验,当一个页面上既有服务器传回的HTML与CSS样式又有原生的UI控件时,UIWebView就会变得特别不好处理,与其他UI控件间的通信也显得很不协调。

        UIWebView处理不好这种问题的原因,是因为它遵循浏览器解析web页面的方式:即逐句解析 。这种解析方式类似于解释型语言,或称脚本语言,只需要下载整段代码中的一部分代码就可以渲染出效果。这不同于一般意义上的编译型语言,如C、C++、Objective-C等,它是在运行的阶段去进行翻译,因此会丧失很多的效率。此外,苹果还为它的webview提供了很多强大的功能,除了最基本的渲染网页上的文字、图片、视频以及交互外,它甚至还可以直接渲染doc、pdf、excel、ppt等一系列常用的文件格式。这么强大的一个控件对系统资源的占用可想而知

         解决这个问题的办法是:把Html+Css字符串直接由服务器传到本地,调用iOS/OS X底层的渲染引擎CoreText去进行渲染。换句话说,这种渲染方式是轻量级的,它去掉了许多Web渲染的繁杂步骤和功能,直接根据Html+Css去渲染图片、文字的样式。当然,根据你的需求,你也可以决定是否处理超链接和显示视频等。

        如下图所示,网易新闻客户端等很多流行的app就是采用类似的方法:

        在这个页面中,布局肯定是不确定,因为所有的文章都是由网易的网编用某种富文本编辑器编写的,虽然会对移动端做一些优化。而下方又有原生的UITableViewCell(评论、其他新闻)以及UIButton等控件,在这种情况下用一个WebView嵌入肯定是不恰当的。

        非常感谢来自澳洲的Oliver Drobnik,秉着开源和分享的精神,为我们提供了完美的框架——DTCoreText。DTCoreText就是笔者所要使用的这种轻量级的Html+Css样式的解析框架。

        以下是在GitHub上的地址以及文档:

            GitHub:https://github.com/Cocoanetics/DTCoreText

            接口文档说明:https://docs.cocoanetics.com/DTCoreText/

        笔者推荐用CocoaPods对DTCoreText进行导入。因为在GitHub上下载的demo中会缺一个子工程:DTFoundation。你还得把这个子工程导入到原工程中。另外如果你想研究以下DTCoreText的底层实现,可以看看下面这篇文章:http://blog.cnbang.net/tech/2630/ 。下面笔者就最近开发遇到的问题做一些总结。

       

        如上图所示,左图的布局中最上部是一个UIImageView,下面是一个分Section的UITableView,包括右图所示的显示评论条目的tableview。下部的评论框是一个单独的UIView控件。在第二个cell中能看到带样式的文字和图片,这个cell就是使用了DTCoreText的结果。在这里,主要是使用

        以下是部分核心代码:

  • @interface DiscoverDetailViewController ()<DiscoverDetailTableViewCellDelegate,DTAttributedTextContentViewDelegate>
  • BOOL _useStaticRowHeight;
  • //    NSArray *_snippets;
  • NSString * const AttributedTextCellReuseIdentifier = @"AttributedTextCellReuseIdentifier";

cellCache类似于tableview的缓存池,用于存放已经生成过的cell

  • - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  • else if (indexPath.section == 2)
  • DTAttributedTextCell *dtcell = (DTAttributedTextCell *)[self tableView:tableView preparedCellForIndexPath:indexPath];

在上面这个确定cell的方法中,省略号部分是其他没有用到DTAttributedTextCell的处理逻辑,可以不破坏这些逻辑,而在你指定的某个indexpath中用到DTCoreText的处理逻辑:类似于tableview的缓存池一样的处理方法。

  • - (DTAttributedTextCell *)tableView:(UITableView *)tableView preparedCellForIndexPath:(NSIndexPath *)indexPath
  • // workaround for iOS 5 bug
  • NSString *key = [NSString stringWithFormat:@"%ld-%ld", (long)indexPath.section, (long)indexPath.row];
  • DTAttributedTextCell *cell = [cellCache objectForKey:key];
  • if ([self _canReuseCells])
  • cell = (DTAttributedTextCell *)[tableView dequeueReusableCellWithIdentifier:AttributedTextCellReuseIdentifier];
  • cell = [[DTAttributedTextCell alloc] initWithReuseIdentifier:AttributedTextCellReuseIdentifier];
  • cell.accessoryType = UITableViewCellAccessoryNone;
  • cell.hasFixedRowHeight = _useStaticRowHeight;
  • // cache it, if there is a cache
  • [cellCache setObject:cell forKey:key];
  • [self configureCell:cell forIndexPath:indexPath];
  • - (void)configureCell:(DTAttributedTextCell *)cell forIndexPath:(NSIndexPath *)indexPath
  • //    NSDictionary *snippet = [_snippets objectAtIndex:indexPath.row];
  • NSString *html = [_dataDictionary objectForKey:@"content"];
  • [cell setHTMLString:html];
  • [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
  • cell.attributedTextContextView.shouldDrawImages = YES;
  • cell.attributedTextContextView.delegate = self;
  • cell.attributedTextContextView.backgroundColor = [ANGUIColorPlus colorWithHexString:@"#efeff4"];
  • - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(nonnull NSIndexPath *)indexPath
  • else if(section == 2)
  • DTAttributedTextCell *cell = (DTAttributedTextCell *)[self tableView:tableView preparedCellForIndexPath:indexPath];
  • return [cell requiredRowHeightInTableView:tableView];

       看到上面这三个方法,笔者感觉非常熟悉,DTCoreText非常遵循UITableView原本的设计方法,对cell的重用管理做得很好。而且,关于确定高度的方法DTAttributedTextCell也给出了一个封装好的自适应高度的方法,使用起来非常方便。

  • // reuse does not work for variable height
  • if ([self respondsToSelector:@selector(tableView:heightForRowAtIndexPath:)])
  • // only reuse cells with fixed height

       上面这个方法用于判断适应当前高度的cell是否可重用,如果可以重用就不需要重新加载了。

       此外,如果要加载图片,还需要实现下面这个代理方法:

  • #pragma mark - DTAttributedTextContentViewDelegate
  • - (UIView *)attributedTextContentView:(DTAttributedTextContentView *)attributedTextContentView viewForAttachment:(DTTextAttachment *)attachment frame:(CGRect)frame{
  • if([attachment isKindOfClass:[DTImageTextAttachment class]]){
  • CGFloat aspectRatio = frame.size.height / frame.size.width;
  • CGFloat width = dUISize_Screen_Width - 16*2;
  • CGFloat height = width * aspectRatio;
  • UIView *View = [[UIView alloc] initWithFrame:frame];
  • UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,width,height)];
  • imageView.backgroundColor = [UIColor grayColor];
  • [imageView sd_setImageWithURL:attachment.contentURL placeholderImage:dImage_loadPicDefault_LongSquare options:EMSDWebImageProgressiveDownload];
  • imageView.canClick = YES;
  • imageView.contentMode = UIViewContentModeScaleAspectFit;
  • [View addSubview:imageView];

          这个代理方法会根据当前要显示图片的url和frame返回一个用于显示图片的UIView。笔者在这里使用SDWebImage作为显示网络图片的方式。然后添加一个UIImageView在View上,这样做可以根据屏幕的大小按比例缩放要显示的图片,以适应显示。

            以上就是实现在UITableView上使用DTCoreText的主要过程。加载的过程很快,滑动时也不会实现卡顿,很流畅。

https://blog.csdn.net/lala2231/article/details/50780842

OS开发小记:iOS富文本框架DTCoreText在UITableView上的使用的更多相关文章

  1. iOS富文本组件的实现—DTCoreText源码解析 数据篇

    本文转载 http://blog.cnbang.net/tech/2630/ DTCoreText是个开源的iOS富文本组件,它可以解析HTML与CSS最终用CoreText绘制出来,通常用于在一些需 ...

  2. iOS富文本(一)属性化字符串

    概述 iOS一些复杂的文本布局一般都是由底层的Core Text来实现的,直到iOS7苹果发布了Text Kit框架,Text Kit能够很简单实现一些复杂的文本样式以及布局,而Text Kit富文本 ...

  3. iOS - 富文本AttributedString

    最近项目中用到了图文混排,所以就研究了一下iOS中的富文本,打算把研究的结果分享一下,也是对自己学习的一个总结. 在iOS中或者Mac OS X中怎样才能将一个字符串绘制到屏幕上呢?         ...

  4. iOS富文本

    背景:前些天突然想做一个笔记本功能,一开始,觉得挺简单的呀,一个UITextView,网络缓存也不干了,直接本地NSUserDefault存储,然后完事了,美工,弄几张好看的图片,加几个动画,也就这样 ...

  5. iOS - 富文本

    iOS--NSAttributedString超全属性详解及应用(富文本.图文混排)   ios项目中经常需要显示一些带有特殊样式的文本,比如说带有下划线.删除线.斜体.空心字体.背景色.阴影以及图文 ...

  6. iOS 富文本类库RTLabel

      本文转载至 http://blog.csdn.net/duxinfeng2010/article/details/9004749  本节关于RTLable基本介绍,原文来自 https://git ...

  7. iOS富文本的使用

    NSString *name = nil; if (_payNumber == 1) { name = [NSString stringWithFormat:@"向%@收款",na ...

  8. iOS富文本-NSAttributedString简单封装

    直接调用系统的写起来比较麻烦,封装一下 因为要简单所以就写类方法 WJAttributeStyle 基类 ) {         ; i < styles.count; i ++) {      ...

  9. ios富文本的简单使用 AttributedString

    富文本,顾名思义就是丰富的文本格式,本文demo使用NSMutableAttributedString //获取富文本 NSMutableAttributedString*attributeStrin ...

随机推荐

  1. 版本管控---Visual Source Safe(VSS)和Team Foundation Server(TFS)

    Visual Source Safe 是用于软件专业开发人员的源代码管理工具 Team Foundation Server是为开发团队提供集成源代码管理.问题跟踪和进程管理的更改管理系统 相同点 1. ...

  2. jQuery事件篇---高级事件

    内容提纲: 1.模拟操作 2.命名空间 3.事件委托 4.on.off 和 one 发文不易,转载请注明出处! 一.模拟操作 在事件触发的时候,有时我们需要一些模拟用户行为的操作.例如:当网页加载完毕 ...

  3. 四、spark集群架构

    spark集群架构官方文档:http://spark.apache.org/docs/latest/cluster-overview.html 集群架构 我们先看这张图 这张图把spark架构拆分成了 ...

  4. K:hash的应用场景

    本博文主要用于讲解Hash的应用场景 Hash主要应用于数据结构中和密码学中. 用于数据结构时,主要是为了提高查询的效率,这就对速度比较重视,对抗碰撞不太看中,只要保证hash均匀分布就可以. 在密码 ...

  5. IEEE VIS 2018专题

    PoPo数据可视化 聚焦于Web数据可视化与可视化交互领域,发现可视化领域有意思的内容.不想错过可视化领域的精彩内容, 就快快关注我们吧 :) 本文带有视频,浏览视频请关注公众号浏览. IEEE VI ...

  6. apply的妙用

    有一个很常见的问题"call和apply的区别是什么?",大家都知道答案:它们的区别仅在于接受参数的方式不同,传递给call的第二个参数必须逐个列举出来,而传递给apply的第二个 ...

  7. 01--CSS的引入方式及CSS选择器

    一 CSS介绍 现在的互联网前端分三层: a.HTML:超文本标记语言.从语义的角度描述页面结构. b.CSS:层叠样式表.从审美的角度负责页面样式. c.JS:JavaScript .从交互的角度描 ...

  8. 关于 PHPMailer 邮件发送类的使用心得(含多文件上传)

    This is important for send mail PHPMailer 核心文件 class.phpmailer.php class.phpmaileroauth.php class.ph ...

  9. canvas createPattern()方法详解

    createPattern作用 createPattern() 方法在指定的方向内重复指定的元素. 元素可以是图片.视频,或者其他 <canvas> 元素. 被重复的元素可用于绘制/填充矩 ...

  10. GDAL线面互转换

    最近因为项目需要,需做GDAL线面互转的功能,查阅部分资料完成,下面把核心部分的代码贴出来,留个记录,也欢迎大家提问题指正完善. /* * @brief ConvertPolygonToPolylin ...