文档章节

扩展于RCLabel的支持异步加载网络图片的富文本引擎的设计

珲少
 珲少
发布于 2015/08/30 23:04
字数 1262
阅读 2168
收藏 12

扩展于RCLabel的支持异步加载网络图片的富文本引擎的设计

        在iOS开发中,图文混排一直都是UI编程的一个核心点,也有许多优秀的第三方引擎,其中很有名的一套图文混排的框架叫做DTCoreText。但是在前些日的做的一个项目中,我并没有采用这套框架,原因有二,一是这套框架体积非常大,而项目的需求其实并不太高;二是要在这套框架中修改一些东西,难度也非常大,我最终采用的是一个叫做RCLabel的第三方控件,经过一些简单的优化和完善,达到了项目的要求。

        先来介绍一下我项目中的图文混排的需求:首先我从服务器中取到的数据是字符串,但是其中穿插图片的位置是一个HTML的图片标签,标签里的资源路径就是图片的请求地址。需要达到的要求是这些数据显示出来后,图片的位置要空出来,然后通过异步的网络请求获取图片的数据,再将图片插入文字中。

        要自己实现一套这样的引擎确实会比较麻烦,幸运的是RCLabel可以完美的帮我们解析带有HTML标签的数据,进行图文混排,我们先来看一下这个东西怎么用,下面是我封装的一个展示html数据的view:

@interface YHBaseHtmlView()<YHRTLabelImageDelegate>
{
    //RCLabel对象
    RCLabel * _rcLabel;
    //保存属性 用于异步加载完成后刷新
    RTLabelComponentsStructure * _origenComponent;
    //含html标签的数据字符串
    NSString * _srt;
}

@end

@implementation YHBaseHtmlView

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/
- (instancetype)initWithCoder:(NSCoder *)coder
{
    self = [super initWithCoder:coder];
    if (self) {
    //将rclabel初始化
        _rcLabel = [[RCLabel alloc]init];
        [self addSubview:_rcLabel];

    }
    return self;
}

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        _rcLabel = [[RCLabel alloc]initWithFrame:frame];
        [self addSubview:_rcLabel];
    }
    return self;
}
-(void)reSetHtmlStr:(NSString *)htmlStr{
    _srt = htmlStr;
    //这个代理是我额外添加的 后面解释
    _rcLabel.imageDelegate=self;
    //设置frame
    _rcLabel.frame=CGRectMake(0, 0, self.frame.size.width, 0);
    //设置属性
    _origenComponent = [RCLabel extractTextStyle:htmlStr IsLocation:NO withRCLabel:_rcLabel];
    _rcLabel.componentsAndPlainText = _origenComponent;
   //获取排版后的size
    CGSize size = [_rcLabel optimumSize];
    //重新设置frame
    _rcLabel.frame=CGRectMake(0, 0, _rcLabel.frame.size.width, size.height);
    self.frame=CGRectMake(self.frame.origin.x, self.frame.origin.y, _rcLabel.frame.size.width, size.height);
}
//这是我额外添加的代理方法的实现
-(void)YHRTLabelImageSuccess:(RCLabel *)label{
    _origenComponent = [RCLabel extractTextStyle:_srt IsLocation:NO withRCLabel:_rcLabel];
    _rcLabel.componentsAndPlainText = _origenComponent;
    
    CGSize size = [_rcLabel optimumSize];
    _rcLabel.frame=CGRectMake(0, 0, _rcLabel.frame.size.width, size.height);
    self.frame=_rcLabel.frame;
    if ([self.delegate respondsToSelector:@selector(YHBaseHtmlView:SizeChanged:)]) {
        [self.delegate YHBaseHtmlView:self SizeChanged:self.frame.size];
    }
}

RCLabel的用法很简单,总结来说只有三步:

1.初始化并设置frame

2.通过带html标签的数据进行属性的初始化

3.将属性进行set设置并重设视图frame

RCLabel是很强大,并且代码很简练,但是其中处理图片的部分必须是本地的图片,即图片html标签中的路径必须是本地图片的名字,其内部是通过[UIImage ImageNamed:]这个方法进行图片的渲染的,所以要达到我们的需要,我们需要对其进行一些简单的扩展:

1、在属性设置方法中添加一个参数,来区分本地图片与网络图片:

//我在这个方法中添加了location这个bool值,实际上rclabel这个参数也是我添加的,是为了后面代理使用的
+ (RTLabelComponentsStructure*)extractTextStyle:(NSString*)dataimage IsLocation:(BOOL)location withRCLabel:(RCLabel *)rcLabel;

2、在实现方法中添加如下代码,因为原文件有1900多行,在其中弄清楚逻辑关系也确实费了我不小的力气,我这里只将我添加的代码贴过来

#warning 这里进行了兼容性处理
                if (location) {
                //本地图片的渲染
                    if (tempURL) {
                        UIImage  *tempImg = [UIImage imageNamed:tempURL];
                        component.img = tempImg;
                        
                    }
                }else{//这里做远程图片数据的处理
                //这里我进行了缓存的操作,这个缓存中心是我封装的框架中的另一套东西,这里可以不用在意
                    //先读缓存
                    NSData * ceche = [[YHBaseCecheCenter sharedTheSingletion] readCecheFile:tempURL fromPath:YHBaseCecheImage];
                    if (ceche) {
                        UIImage * tempImg = [UIImage imageWithData:ceche];
                        component.img=tempImg;
                    }else{
                    //在分线程中进行图片数据的获取
                        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
                            if (tempURL) {
                                NSData * data = [YHBaseData getDataWithUrl:tempURL];
                                if (data) {
                                //获取完成后村缓存
                                    //做缓存
                                    [[YHBaseCecheCenter sharedTheSingletion]writeCecheFile:data withFileID:tempURL toPath:YHBaseCecheImage];
                                    //赋值 回调代理
                                    UIImage * tempImg = [UIImage imageWithData:data];
                                    component.img=tempImg;
                                    //这里代理是我添加的,当图片下载完成后 通知视图重新排版
                                    if ([[rcLabel imageDelegate]respondsToSelector:@selector(YHRTLabelImageSuccess:)]) {
                                        //在主线程中执行回调
                                        //这个地方要在主线程中执行,否则刷新会有延时
                                        dispatch_async(dispatch_get_main_queue(), ^{
                                             [[rcLabel imageDelegate] YHRTLabelImageSuccess:rcLabel];
                                        });
                            
                                    }
                                   
                                }
                                
                            };
                            
                        });
                    }
                   
                    
                }

通过如上简单的扩展,基本达到了项目中的需求,这里把我的一些想法和思路分享给大家,有更好的解决方案,或者同是开发爱好者,欢迎指点与交流,我的QQ是316045346。

专注技术,热爱生活,交流技术,也做朋友。

——珲少 QQ群:203317592

© 著作权归作者所有

珲少

珲少

粉丝 886
博文 394
码字总数 475753
作品 0
上海
程序员
私信 提问
加载中

评论(3)

sunshineAK
sunshineAK

引用来自“xwlyun”的评论

RCLabel里的图片只能来自本地,不能直接显示网络,这个问题你解决了吗?

引用来自“珲少”的评论

解决了 那个显示超链接的 我是做成类似attributeString的形式 省去html的转化了
您好,有没有完整的demo提供呢?显示网络图片的,有的话麻烦发个。。谢谢
珲少
珲少 博主

引用来自“xwlyun”的评论

RCLabel里的图片只能来自本地,不能直接显示网络,这个问题你解决了吗?
解决了 那个显示超链接的 我是做成类似attributeString的形式 省去html的转化了
xwlyun
xwlyun
RCLabel里的图片只能来自本地,不能直接显示网络,这个问题你解决了吗?
iOS开发封装一个可以响应超链接的label——基于RCLabel的交互扩展

iOS开发封装一个可以响应超链接的label——基于RCLabel的交互扩展 一、引言 iOS系统是一个十分注重用户体验的系统,在iOS系统中,用户交互的方案也十分多,然而要在label中的某部分字体中添加...

珲少
2015/12/23
3K
1
iOS文本布局探讨之三——使用TextKit框架进行富文本布局

iOS文本布局探讨之三——使用TextKit框架进行富文本布局 一、引言 关于图文混排,其实以前的博客已经讨论很多,在实际开发中,经常使用第三方的框架来完成排版的需求,其中RCLabel和RTLabel...

珲少
2016/09/10
1K
0
iOS中支持HTML文本的标签控件——MDHTMLLabel

iOS中支持HTML文本的标签控件——MDHTMLLabel 一、引言 在iOS开发中对HTML的处理很多时候除了使用WebView外,还需要原生的控件对其进行渲染,例如将HTML字符串渲染为图文混排的View视图。Git...

珲少
2016/06/30
2.2K
0
iOS 轻量级富文本框架 - ZJAttributedText

ZJAttributedText 是高性能轻量级富文本框架 前言 如果遇到上面一个需求, 你会怎么处理, 若干个 UILabel + UIImageView? NSAttributedString拼接? CoreText? 我相信不论是哪种方式代码量都不...

Syik
2018/06/29
319
0
ZJAttributedText 0.1.1 支持 Layer 与 View 的混排

ZJAttributedText 0.1.1 发布了,ZJAttributedText 是高性能的轻量级富文本框架,满足大部分富文本需求,并且提供了手势响应、绘制回调、图文对齐、CoreText 属性扩展、支持网络图片、异步绘...

h4cd
2018/06/29
331
0

没有更多内容

加载失败,请刷新页面

加载更多

Android面试常客之Handler全解

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/fnhfire_7030/article/details/79518819 前言:又到了一年...

shzwork
3分钟前
0
0
position sticky 定位

本文转载于:专业的前端网站➫position sticky 定位 1、兼容性 https://caniuse.com/#search=sticky chrome、ios和firefox兼容性良好。 2、使用场景 sticky:粘性。粘性布局。 在屏幕范围内时...

前端老手
10分钟前
1
0
CentOS 7 yum 安装 PHP7.3 教程

参考:https://www.mf8.biz/centos-rhel-install-php7-3/ 1、首先安装 EPEL 源: yum install epel-release 安装 REMI 源: yum install http://rpms.remirepo.net/enterprise/remi-release......

dragon_tech
25分钟前
1
0
Linux物理网卡聚合及桥接

Linux内部实现的bridge可以把一台机器上的多张网卡桥接起来,从而把自己作为一台交换机。同时,LInux bridge还支持虚拟端口,即桥接的不一定都是物理网卡接口,还可以是虚拟接口。目前主要表...

xiangyunyan
25分钟前
1
0
一起来学Java8(一)——函数式编程

在这篇文章中,我们将了解到在Java8下如何进行函数式编程。 函数式编程 所谓的函数式编程就是把函数名字当做值进行传递,然后接收方拿到这个函数名进行调用。 首先来看下JavaScript如何进行函...

猿敲月下码
57分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部